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>
This commit is contained in:
2026-06-15 23:48:49 +02:00
parent b21efe307b
commit cdcf4b09aa
3 changed files with 91 additions and 0 deletions

View File

@@ -9,6 +9,7 @@ Background on document types: InfoTechPrimers on coulomb.social.
| `CoreArchitectureBlueprint.md` | draft for review | **Whole-system architecture** — layers, abstractions, load-bearing decisions (synthesised from all research) |
| `FederationArchitecture.md` | draft for review | federation design — *what the union does*: T1T10 decision records + the federation-model taxonomy (SHARD-WP-0002) |
| `WikiEngineCoreArchitecture.md` | draft for review | the native **headless, API-first wiki engine** — small page-store kernel + typed-extension framework, as a canonical-mode shard backend (SHARD-WP-0013) |
| `adr/` | living | Architecture Decision Records (ADR-0001: engine activation via feature-control) |
| `FederationRequirements.md` | draft for review | yawex-derived union/federation design notes — resolution, namespace, derived views, provenance, overlay, links (ADR-01…06; SHARD-WP-0001) |
| `ProductRequirementsDocument.md` | draft scaffold | What the product must deliver |
| `TechnicalSpecificationDocument.md` | draft + §A | How the system is built; **§A = the normative shard adapter contract** (T11T16, T18; SHARD-WP-0002) |

View File

@@ -0,0 +1,79 @@
# 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`.

11
spec/adr/README.md Normal file
View File

@@ -0,0 +1,11 @@
# spec/adr/ — Architecture Decision Records
Repository-level ADRs: one decision per file, `ADR-NNNN-<slug>.md`, status
**Proposed / Accepted / Superseded**. Each records Context · Decision · Consequences ·
Alternatives. These are the standalone, numbered decision log; design-note "ADRs" embedded
inside a spec (e.g. `FederationRequirements.md` ADR-01…06) are scoped to that document and are
not part of this series.
| ADR | Status | Subject |
|-----|--------|---------|
| [ADR-0001](ADR-0001-engine-activation-via-feature-control.md) | Accepted | Engine extension activation via feature-control (OpenFeature), availability-only, LocalProvider standalone default |