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>
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.mdcontains document-internal "ADR-01…06" design notes — those are scoped to that spec; thisspec/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 mechanism — availability only — with these constraints:
- OpenFeature-shaped, provider-pluggable. The engine evaluates activation through an
OpenFeature-style client. A static
LocalProvideris the standalone/L0 default (zero external dependency); afeature-control/remote provider is plugged in for governed deployments. This mirrors shard-wiki's existing identity-provider ladder (null/local default → external when present). - 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.) - Engine layer, not the orchestrator foundation. Integration lives in
engine/activation.py; the currentsrc/shard_wiki/core stays dependency-free. OpenFeature/ feature-control is an optional extra, kept out of the standalone path by theLocalProvider. - 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.
Related
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.