generated from coulomb/repo-seed
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>
80 lines
4.7 KiB
Markdown
80 lines
4.7 KiB
Markdown
# 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 mechanism** — *availability 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.
|
|
|
|
## 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`.
|