diff --git a/spec/README.md b/spec/README.md index ce6d230..f67e3ac 100644 --- a/spec/README.md +++ b/spec/README.md @@ -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*: T1–T10 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** (T11–T16, T18; SHARD-WP-0002) | diff --git a/spec/adr/ADR-0001-engine-activation-via-feature-control.md b/spec/adr/ADR-0001-engine-activation-via-feature-control.md new file mode 100644 index 0000000..d0e78fb --- /dev/null +++ b/spec/adr/ADR-0001-engine-activation-via-feature-control.md @@ -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`. diff --git a/spec/adr/README.md b/spec/adr/README.md new file mode 100644 index 0000000..4bd521f --- /dev/null +++ b/spec/adr/README.md @@ -0,0 +1,11 @@ +# spec/adr/ — Architecture Decision Records + +Repository-level ADRs: one decision per file, `ADR-NNNN-.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 |