Files
shard-wiki/spec/adr/ADR-0001-engine-activation-via-feature-control.md
tegwick cdcf4b09aa adr: ADR-0001 engine activation via feature-control (OpenFeature, availability-only)
Records the accepted decision: shard-wiki's native engine uses feature-control via
OpenFeature for per-shard extension activation (availability only, never authz),
provider-pluggable with a LocalProvider standalone default (mirrors the identity
ladder), at the engine layer, consuming the mature feature-control.evaluate slice.
Adds spec/adr/ series + README; hub decision abf7830f recorded.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 23:48:49 +02:00

4.7 KiB

ADR-0001 — Engine extension activation via feature-control (OpenFeature)

Status: Accepted · Date: 2026-06-15 · Deciders: tegwick · Source: SHARD-WP-0013 follow-up (feature-control assessment)

First repo-level ADR. (Note: FederationRequirements.md contains document-internal "ADR-01…06" design notes — those are scoped to that spec; this spec/adr/ series is the repository's standalone architecture decision log, starting here.)

Context

WikiEngineCoreArchitecture.md (SHARD-WP-0013 T5) defines the engine as a small kernel plus a typed-extension framework where each shard activates only the extensions it needs (invariants E-4 activation, E-8 reuse-not-reinvent). It needs a mechanism to decide, per shard (and per tenant/context), which extensions/features are active — without baking a bespoke flag system into the engine, and without breaking the standalone, zero-external-dependency L0 posture shard-wiki guarantees.

The helix_forge sibling feature-control (capability.feature-control.evaluate, registered at D5 / A4 / C3 / R3) provides exactly this: an OpenFeature-based feature-availability control plane with a working SDK (feature_control_sdk: FeatureControlClient, Resolver, a static LocalProvider), context-scoped evaluation (tenant_id/scope), explainable decisions, and graceful degradation when OpenFeature is absent. shard-wiki already proposed this as a T3 consumption (reuse, don't rebuild).

Decision

Adopt feature-control (via the OpenFeature standard) as the engine's per-shard extension/ feature activation mechanismavailability only — with these constraints:

  1. OpenFeature-shaped, provider-pluggable. The engine evaluates activation through an OpenFeature-style client. A static LocalProvider is the standalone/L0 default (zero external dependency); a feature-control/remote provider is plugged in for governed deployments. This mirrors shard-wiki's existing identity-provider ladder (null/local default → external when present).
  2. Availability ≠ authorization. feature-control decides which extensions are active, never who may read/write. Authorization stays in core (X-AUTHZ / authorization.policy- evaluate). The two are composed but never conflated. (feature-control's own INTENT requires this.)
  3. Engine layer, not the orchestrator foundation. Integration lives in engine/activation.py; the current src/shard_wiki/ core stays dependency-free. OpenFeature/ feature-control is an optional extra, kept out of the standalone path by the LocalProvider.
  4. Thin slice only. Consume feature-control.evaluate (mature, A4). Do not take a dependency on the heavier control-plane governance / rollout / visibility (A2) until a concrete need appears.

Activation keys = extension ids; evaluation context = {tenant_id: root-entity, shard_id, …}; the resulting active-extension set then derives the shard's §A capability profile (E-5).

Consequences

Positive

  • No bespoke flag system; reuses a mature (D5/A4) capability — reuse-surface aligned.
  • Standalone stays zero-dep (LocalProvider); governed deployments get real runtime control, multi-tenant scoping, and explainable decisions that feed the engine's agent-introspection API (E-7: "why is extension X off for this shard?").
  • "Activate only what you need" + compute control become first-class and reversible at runtime.
  • Clean layering: availability (feature-control) vs authorization (core) vs identity (provider).

Negative / risks (mitigated by the constraints)

  • An optional OpenFeature dependency at the engine layer (mitigated: out of the standalone path).
  • Coupling to an external control plane in governed mode (mitigated: provider-pluggable, degrade to LocalProvider).
  • Temptation to route authz through it (mitigated: constraint 2, hard boundary).

Alternatives considered

  • Bespoke per-shard flag/config in the engine — rejected: reinvents feature-control, no standard, no multi-tenant/explainability, violates reuse-not-reinvent (E-8).
  • No activation (all extensions always on) — rejected: defeats "small core + activate only what you need" (E-2/E-4) and the compute-control goal.
  • Build on the heavier feature-control control-plane now — deferred: over-scoping a single engine's activation; revisit if rollout/governance needs emerge.

WikiEngineCoreArchitecture.md (E-4/E-8, §4 activation), UseCaseCatalog.md capability-structure layer (X-AUTHZ vs activation), history/260615-reuse-surface-contributions.md (T3 consumption), reuse-surface capability.feature-control.evaluate, INTENT amendment decision 84ffdb48.