Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
693976c289 | ||
|
|
b1a1c9bc86 | ||
|
|
2a229bbf3f | ||
|
|
b8f0abdb0d | ||
|
|
ee0c094398 | ||
|
|
1fba3d9f95 |
@@ -0,0 +1,87 @@
|
||||
# ADR-002: Node.js 24 LTS runtime
|
||||
|
||||
- Status: Accepted
|
||||
- Date: 2026-08-31
|
||||
- Deciders: platform stream
|
||||
- References: ADR index (section 70), Technology stack wiki (sections 5.2, 6, 7, 8), ADR-001
|
||||
|
||||
## Context
|
||||
|
||||
EPPP is a greenfield personal blogging platform (ADR-001) whose runtime is a
|
||||
single modular-monolith application plus an optional worker, deployed as one
|
||||
or more containers of one image. The whole platform — public server, admin
|
||||
API, rendering pipeline, extension runtime, core services and background
|
||||
jobs — executes on one runtime, so the runtime choice is a platform-wide,
|
||||
hard-to-reverse decision with security, tooling and operational reach.
|
||||
|
||||
The workspace is a pnpm monorepo (pnpm 11.23.0) whose root manifest already
|
||||
declares `engines.node: ">=24.0.0 <25.0.0"` with `engineStrict: true`, and
|
||||
the CI pipeline installs and runs on Node 24 (E00-S01-T08). The technology
|
||||
stack wiki classifies Node.js as support class A — a fixed upstream EOL date
|
||||
— and pins the golden compatibility tuple to Node 24.19.0 LTS (Krypton), with
|
||||
`node:24.19.0-bookworm-slim` as the application container base image.
|
||||
|
||||
## Decision
|
||||
|
||||
EPPP runs on the **Node.js 24 LTS** runtime line, exact-pinned to Node 24.19.0
|
||||
LTS (Krypton) in the golden compatibility tuple and the container image. The
|
||||
workspace root manifest restricts the engine to 24.x
|
||||
(`engines.node: ">=24.0.0 <25.0.0"`), pnpm enforces it at install time
|
||||
(`engineStrict: true`), and CI installs and runs on Node 24. The runtime is a
|
||||
class A dependency: its upstream EOL (2028-04-30) drives the upgrade
|
||||
schedule, and a move to a later major line (for example Node 26) is only
|
||||
evaluated once that line is LTS and the compatibility suite passes, and then
|
||||
only as a deliberate, ADR-recorded change. The decision text — **Node.js 24
|
||||
LTS runtime** — matches the ADR index entry (ADR-002, section 70).
|
||||
|
||||
## Alternatives
|
||||
|
||||
- **Node 22 LTS (Jod)** — rejected: it is the previous LTS line and reaches
|
||||
EOL before Node 24 (2027-04-30), shortening the runway for a platform whose
|
||||
v1.1 boundary contracts (ADR-027 to ADR-032) extend past that date.
|
||||
- **Node 26 (current, non-LTS at decision time)** — rejected: not LTS when
|
||||
the decision was made; running a non-LTS line contradicts the class A
|
||||
support posture (fixed EOL, security patching on an LTS cadence).
|
||||
- **Node 24 with no exact pin (floating latest 24.x)** — rejected: a floating
|
||||
minor would break the reproducibility of the golden compatibility tuple and
|
||||
the container image; the line is pinned and minors move deliberately.
|
||||
- **Node 24 LTS, exact-pinned 24.19.0** — chosen: an LTS major with a fixed
|
||||
EOL, exact-pinned in the image and tuple, engine-restricted in the
|
||||
manifest, and enforced in CI.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Positive: an LTS line with a fixed upstream EOL (2028-04-30) gives a
|
||||
predictable security-patching and upgrade horizon; the exact pin makes
|
||||
builds and containers reproducible; the engine restriction rejects
|
||||
unsupported Node versions at install time instead of failing at runtime.
|
||||
- Negative: Node 24 API and behaviour become the platform floor — anything
|
||||
needing a newer Node feature waits for the deliberate, ADR-recorded major
|
||||
upgrade; minor upgrades inside 24.x still need the weekly dependency sweep
|
||||
and full CI.
|
||||
- Neutral: the runtime is shared by every module, so a future extraction
|
||||
(ADR-001) keeps running on the same Node line until that module's runtime
|
||||
needs diverge.
|
||||
|
||||
## Operational impact
|
||||
|
||||
- Application and worker containers run `node:24.19.0-bookworm-slim`; release
|
||||
automation records the immutable image digest in the SBOM/release manifest.
|
||||
- The supported runtime is enforced at install (`engineStrict: true` fails
|
||||
installs on unsupported Node) and at test time (the node-engine suite
|
||||
asserts the current runtime satisfies the 24.x range).
|
||||
- CI installs and runs every stage on Node 24, so the committed pipeline is
|
||||
the operational proof that the platform runs on the chosen line.
|
||||
- Node 24 is patched on the LTS cadence; security-emergency updates go
|
||||
through the focused lane (immediate, full CI), and the EOL date is the
|
||||
deadline for the next major-line ADR.
|
||||
|
||||
## Revisit trigger
|
||||
|
||||
- Revisit when Node 26 becomes LTS and passes the compatibility suite, per
|
||||
the LTS strategy — the decision to move majors is a new ADR, not a patch.
|
||||
- Revisit on a security-emergency or patch-lane event that forces a minor
|
||||
upgrade outside the weekly sweep, or if upstream announces a change to the
|
||||
Node 24 support horizon.
|
||||
- Revisit if a module's runtime needs (ADR-001 extraction) diverge from the
|
||||
shared Node line and a second runtime enters the platform.
|
||||
@@ -0,0 +1,86 @@
|
||||
# ADR-003: TypeScript 6.0.3 language decision
|
||||
|
||||
- Status: Accepted
|
||||
- Date: 2026-08-31
|
||||
- Deciders: platform stream
|
||||
- References: ADR index (section 70), Technology stack wiki (sections 5.2, 6, 7, 8), ADR-001
|
||||
|
||||
## Context
|
||||
|
||||
EPPP is a modular monolith (ADR-001) written in TypeScript across every
|
||||
module boundary: `apps/`, `packages/` and `extensions/` are all compiled from
|
||||
strict TypeScript against a shared base tsconfig (E00-S01-T10). The language
|
||||
version is therefore a platform-wide decision: it fixes the type-system
|
||||
features, the compiler behaviour and the toolchain (editor, build, CI
|
||||
typecheck) every module sees.
|
||||
|
||||
The workspace already pins TypeScript exactly: the root manifest declares
|
||||
`devDependencies.typescript: "6.0.3"` (a bare MAJOR.MINOR.PATCH, no semver
|
||||
range), the committed lockfile resolves exactly one `typescript@6.0.3`, and
|
||||
every workspace package resolves `Version 6.0.3` (E00-S01-T09). The
|
||||
technology stack wiki classifies TypeScript as support class C — rolling,
|
||||
exact-pinned, tested and upgraded deliberately — and pins 6.0.3 in the golden
|
||||
compatibility tuple. TypeScript 7.0 reached GA in 2026-07 without a stable
|
||||
programmatic API before 7.1, making 6.0 the bridge release.
|
||||
|
||||
## Decision
|
||||
|
||||
EPPP uses **TypeScript 6.0.3** as its language and compiler, exact-pinned in
|
||||
the root manifest and the lockfile so every workspace package and every CI
|
||||
typecheck runs the identical compiler. 6.0.3 is the baseline; a formal review
|
||||
happens after TS 7.1 is stable (per the technology stack LTS strategy), and
|
||||
any move to the 7.x line is a deliberate, ADR-recorded change. The decision
|
||||
text — **TypeScript 6.0.3 pending TS7.1 ecosystem review** — matches the ADR
|
||||
index entry (ADR-003, section 70).
|
||||
|
||||
## Alternatives
|
||||
|
||||
- **TypeScript 7.0 at GA (2026-07)** — rejected: it shipped without a stable
|
||||
programmatic API before 7.1, which would put the compiler toolchain on an
|
||||
unstable surface; 6.0 is the documented bridge.
|
||||
- **TypeScript 6.x floating (caret/range)** — rejected: a range could resolve
|
||||
to a different compiler than the one the golden tuple was tested with; the
|
||||
exact pin is what makes typecheck deterministic across modules and CI.
|
||||
- **TypeScript 5.x (previous major)** — rejected: it predates the 6.0 type
|
||||
system and ecosystem position the platform was bootstrapped on; staying on
|
||||
an older major only delays the bridge.
|
||||
- **TypeScript 6.0.3 exact-pinned** — chosen: the bridge release, exact-pinned
|
||||
and CI-verified, with a formal re-review once TS 7.1 stabilises the
|
||||
programmatic API.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Positive: one exact compiler version across apps, packages and extensions
|
||||
makes typecheck results reproducible locally and in CI; the 6.0 bridge is a
|
||||
known-good stepping stone to the 7.x line; strict mode across the workspace
|
||||
stays uniform.
|
||||
- Negative: the language feature set is fixed at 6.0.3 until the reviewed
|
||||
upgrade; any tooling that needs the 7.x programmatic API waits for the TS
|
||||
7.1 formal review.
|
||||
- Neutral: upgrades inside the pinned major remain controlled by the
|
||||
dependency sweep; the language choice is invisible to the deployed runtime
|
||||
(TypeScript compiles away) but is enforced at build and typecheck time.
|
||||
|
||||
## Operational impact
|
||||
|
||||
- `pnpm install --frozen-lockfile` resolves exactly `typescript@6.0.3`; the
|
||||
lockfile contains one resolved TypeScript entry, so no package can drift
|
||||
onto another version.
|
||||
- Every workspace `build`/`typecheck` script invokes the pinned compiler
|
||||
(`pnpm exec tsc`), and the typescript-pin suite asserts each package
|
||||
resolves `Version 6.0.3`.
|
||||
- CI stage 2 (typecheck) runs `pnpm typecheck` across the workspace, so the
|
||||
language pin is continuously verified on every pull request.
|
||||
- A TypeScript upgrade is a class C lane change: patch/minor through the
|
||||
sweep with full CI; the 7.x major is a programme item with its own ADR.
|
||||
|
||||
## Revisit trigger
|
||||
|
||||
- Revisit after TypeScript 7.1 is stable: the formal review (per the LTS
|
||||
strategy) decides whether the platform moves to the 7.x line, recorded as a
|
||||
new ADR.
|
||||
- Revisit if a workspace package needs a type-system feature or toolchain
|
||||
capability that 6.0.3 cannot provide, or if the ecosystem (editors, tools,
|
||||
type packages) leaves the 6.0 bridge unsupported.
|
||||
- Revisit if a module boundary contract (ADR-027 to ADR-032) becomes
|
||||
unrepresentable in the pinned type system.
|
||||
@@ -0,0 +1,136 @@
|
||||
# ADR-004: Fastify 5 HTTP runtime
|
||||
|
||||
- Status: Accepted
|
||||
- Date: 2026-08-31
|
||||
- Deciders: platform stream
|
||||
- References: ADR index (section 70), Technology stack wiki (sections 5.2, 6,
|
||||
7, 8), Architecture wiki (sections 1, 19, 42), ADR-001, ADR-002
|
||||
|
||||
## Context
|
||||
|
||||
EPPP is a modular monolith (ADR-001) whose single application image contains
|
||||
the public server, admin API, rendering pipeline, extension runtime and core
|
||||
services. Every inbound request — public pages, the admin API and the
|
||||
health/readiness endpoints — enters the platform through one HTTP runtime, so
|
||||
the runtime choice is a platform-wide, hard-to-reverse decision with security,
|
||||
tooling and operational reach.
|
||||
|
||||
The public rendering pipeline is already documented as starting at the HTTP
|
||||
layer — `Fastify route → SiteResolver → VisitorPreferenceResolver →
|
||||
ContentService → PageComposition + BlockRegistry → ThemeResolver → React DOM
|
||||
server renderer → HTML` (Architecture wiki §19) — and the v0.1 public surface
|
||||
(§42) exposes `GET /`, `GET /posts/:slug`, `GET /assets/*`, `GET /media/*`,
|
||||
`GET /health/live`, `GET /health/ready` and `GET /admin/*`, all served by the
|
||||
HTTP runtime.
|
||||
|
||||
The choice is already recorded higher up: ADR-001 fixes the runtime as
|
||||
"Node.js 24 LTS with Fastify 5" and ADR-002 records the Node line. The
|
||||
technology stack wiki pins **Fastify 5.12.1** in the golden compatibility
|
||||
tuple (§7) as support class B — a documented support policy with no fixed
|
||||
multi-year EOL date (§5.2) — and lists the approved Fastify lifecycle
|
||||
plugins: `@fastify/cookie` 11.1.2, `helmet` 13.1.1, `@fastify/rate-limit`
|
||||
11.2.0, `@fastify/static` 10.1.3, `@fastify/csrf-protection` 8.0.1,
|
||||
`@fastify/swagger` 9.8.1, with `@fastify/multipart` 10.1.1 behind a CI gate
|
||||
(§5.2).
|
||||
|
||||
The workspace currently boots a minimal `node:http` server for the health
|
||||
endpoint (E00-S02-T03) — explicitly documented as a bootstrap until "the
|
||||
Fastify 5 application shell (and the real HTTP API) lands in a later story" —
|
||||
so this ADR formalises the committed runtime decision ahead of that shell.
|
||||
|
||||
## Decision
|
||||
|
||||
EPPP serves all inbound HTTP on the **Fastify 5 HTTP runtime**, exact-pinned
|
||||
to Fastify 5.12.1 in the golden compatibility tuple (Technology stack §7).
|
||||
One Fastify 5 application hosts the public routes, the admin API under
|
||||
`/api/admin/v1/*` and the health/readiness endpoints; the temporary
|
||||
`node:http` bootstrap is replaced when the Fastify 5 application shell lands
|
||||
in a later story.
|
||||
|
||||
Fastify's plugin encapsulation matches the platform's module-boundary
|
||||
discipline (ADR-001): the approved plugin set is the Fastify lifecycle list
|
||||
in the technology stack (§5.2) — cookie, helmet, rate-limit, static,
|
||||
csrf-protection, swagger, with multipart gated in CI before enabling — and
|
||||
Fastify's native Pino 10.3.1 logger is the platform logger (the existing
|
||||
secret-redaction requirement, E00-S04-T03, carries over).
|
||||
|
||||
Fastify is support class B: it has no fixed upstream EOL, and an upgrade to
|
||||
Fastify 6 is a deliberate, ADR-recorded major change gated on a stable v6,
|
||||
all required plugins compatible, the full suite green, and extension
|
||||
contracts stable/migrated (§6). The decision text — **Fastify 5 HTTP
|
||||
runtime** — matches the ADR index entry (ADR-004, section 70).
|
||||
|
||||
## Alternatives
|
||||
|
||||
- **Express (4.x/5.x)** — rejected: the middleware-chain model has no
|
||||
first-class request/response schema validation or serialization, which
|
||||
conflicts with the JSON Schema + TypeBox + Ajv validation decision
|
||||
(ADR-011); plugin encapsulation and lifecycle hooks are weaker than
|
||||
Fastify's, and the community middleware surface is less uniform to pin.
|
||||
- **Hono** — rejected: it is oriented toward edge/serverless runtimes, which
|
||||
conflicts with the long-lived process model, background jobs and
|
||||
connection-backed PostgreSQL access chosen in ADR-001; the golden tuple and
|
||||
extension contracts were bootstrapped on Fastify.
|
||||
- **Koa** — rejected: the minimal core requires assembling routing, body
|
||||
parsing, validation, security headers and logging by hand, adding glue code
|
||||
with no schema-based validation story.
|
||||
- **Bare `node:http`** — rejected for the real API: it is only the temporary
|
||||
health bootstrap (E00-S02-T03); it provides no routing, plugin lifecycle,
|
||||
validation or the ecosystem the v0.1 public surface (§42) needs.
|
||||
- **Fastify 5** — chosen: schema-based validation and serialization aligns
|
||||
with ADR-011, plugin encapsulation matches the module boundaries (ADR-001),
|
||||
Pino logging is native, TypeScript support is first-class, and the
|
||||
lifecycle plugin set is already pinned in the stack (§5.2).
|
||||
|
||||
## Consequences
|
||||
|
||||
- Positive: schema-based request/response validation and serialization aligns
|
||||
with the ADR-011 decision (JSON Schema + TypeBox + Ajv); plugin
|
||||
encapsulation gives each plugin an isolated scope, matching the
|
||||
module-boundary discipline of ADR-001; the runtime is already the documented
|
||||
choice in ADR-001 and the golden tuple, so no rework is needed when the
|
||||
application shell lands; native Pino 10.3.1 logging integrates with the
|
||||
existing redaction requirement (E00-S04-T03); the pinned lifecycle plugin
|
||||
set covers the v0.1 needs — cookies/opaque DB-backed sessions (ADR-019),
|
||||
security headers, rate limiting, static assets/media and swagger docs.
|
||||
- Negative: Fastify 5 is class B — no fixed upstream EOL date, so the support
|
||||
horizon is policy-defined rather than date-defined; the exact pin (5.12.1)
|
||||
must move deliberately through the dependency lanes; the application shell
|
||||
does not exist yet, so this ADR commits a decision whose implementation
|
||||
lands in a later story (the `node:http` bootstrap remains until then).
|
||||
- Neutral: Fastify is an in-process library, so a future module extraction
|
||||
(ADR-001) does not change the shared HTTP runtime unless that module needs
|
||||
its own runtime; plugin majors move through the update lanes like any class
|
||||
B dependency.
|
||||
|
||||
## Operational impact
|
||||
|
||||
- One Fastify 5 process serves the public routes, admin API and
|
||||
health/readiness endpoints; it binds the validated `HOST`/`PORT` from the
|
||||
config adapter (E00-S04-T04).
|
||||
- Health/readiness remain part of the v0.1 surface (`GET /health/live`,
|
||||
`GET /health/ready`, Architecture wiki §42) with readiness gated on
|
||||
migration completion (E00-S03-T06).
|
||||
- All log output continues through the redacting-logger pattern (E00-S04-T03);
|
||||
Fastify's native Pino logger is configured with the same redaction.
|
||||
- The security posture comes from the approved plugin set: helmet (headers),
|
||||
csrf-protection (state-changing requests), rate-limit (abuse), cookie
|
||||
(opaque DB-backed admin sessions, ADR-019), static (assets/media) and
|
||||
swagger (API docs).
|
||||
- Deploy/rollback is unchanged: the HTTP runtime lives inside the single
|
||||
application image (ADR-001), so rollback is redeploying the previous image.
|
||||
- Fastify patch/minor upgrades go through the weekly dependency sweep with
|
||||
full CI; a Fastify 6 major is a programme item (ADR + compatibility + full
|
||||
suite + plugin migration, §6/§8).
|
||||
|
||||
## Revisit trigger
|
||||
|
||||
- Revisit when Fastify 6 is stable, all required lifecycle plugins are
|
||||
compatible, the full suite is green and the extension contracts are
|
||||
stable/migrated — per the LTS strategy (§6) the move to v6 is a new ADR, not
|
||||
a patch.
|
||||
- Revisit if the Fastify 5 support policy changes (class B has no fixed EOL
|
||||
date), or if a required plugin forces a Fastify major earlier than planned.
|
||||
- Revisit if the Fastify 5 application shell, when it lands, cannot satisfy
|
||||
the v0.1 public surface (§42) or the v1.1 boundary contracts (ADR-027 to
|
||||
ADR-032) — for example, a hard requirement Fastify 5 cannot meet.
|
||||
@@ -3,9 +3,8 @@
|
||||
- Status: Accepted
|
||||
- Date: 2026-08-31
|
||||
- Deciders: platform stream
|
||||
- References: ADR index (docs/adr/README.md, section 70), ADR-001, ADR-005,
|
||||
Architecture wiki (sections 1, 4, 9), Engineering-Standards wiki
|
||||
(sections 24, 25, 57)
|
||||
- References: ADR-001, ADR-005, Architecture wiki (sections 1, 4, 9),
|
||||
Engineering-Standards wiki (sections 24, 25, 57)
|
||||
|
||||
## Context
|
||||
|
||||
@@ -50,9 +49,6 @@ CI gate plus FIT-010/FIT-011 enforce this on every PR. Kysely exists only
|
||||
where the adapter lives — it is contained, not distributed, and the containment
|
||||
is a package-level rule, not a type-level one.
|
||||
|
||||
The decision text — **Kysely contained inside DB adapter** — matches the ADR
|
||||
index entry (ADR-006, section 70 of `docs/adr/README.md`).
|
||||
|
||||
## Alternatives
|
||||
|
||||
- **Kysely imported directly by domain/extension packages** — rejected: it
|
||||
@@ -81,10 +77,11 @@ index entry (ADR-006, section 70 of `docs/adr/README.md`).
|
||||
|
||||
- Positive: one owner for the whole driver/query-builder stack — upgrade,
|
||||
dialect and typing decisions live in `packages/database-postgres` and are
|
||||
exact-pinned single-manifest changes (ADR-026 lane); domain and extension
|
||||
code stays driver-free, so FIT-010/FIT-011 hold; replacing Kysely or the
|
||||
dialect later is a contained change behind the adapter boundary (consistent
|
||||
with the ADR-005 encapsulation).
|
||||
exact-pinned single-manifest changes, so replacing or upgrading Kysely and
|
||||
`pg` touches exactly one manifest; domain and extension code stays
|
||||
driver-free, so FIT-010/FIT-011 hold; replacing Kysely or the dialect later
|
||||
is a contained change behind the adapter boundary (consistent with the
|
||||
ADR-005 encapsulation).
|
||||
- Negative: the adapter's port/repository API must be designed well enough
|
||||
that domain code never needs the query builder — the port API is mandatory,
|
||||
not optional; Kysely conveniences (expression builders, plugin features) are
|
||||
@@ -102,7 +99,7 @@ index entry (ADR-006, section 70 of `docs/adr/README.md`).
|
||||
(`database-postgres-imports` CI job) proves it on every PR, including a
|
||||
mutation probe that fails when a driver import is injected elsewhere.
|
||||
- Upgrading Kysely or `pg` is a single-manifest change inside the adapter,
|
||||
reviewed under the dependency/upgrade lane (ADR-026); no other package's
|
||||
reviewed under the workspace's dependency/upgrade lane; no other package's
|
||||
manifest or code moves.
|
||||
- No new runtime services, no schema changes, no deployment or configuration
|
||||
impact: this ADR is documentation of an already-enforced boundary.
|
||||
@@ -111,9 +108,8 @@ index entry (ADR-006, section 70 of `docs/adr/README.md`).
|
||||
|
||||
- Revisit this ADR when a non-adapter package demonstrably needs
|
||||
query-builder features that cannot be expressed through the adapter/port
|
||||
API, and there is evidence (per the architecture review gates, ADR index
|
||||
§68 of `docs/adr/README.md`) that the boundary costs more than containment
|
||||
saves.
|
||||
API, and there is evidence (per the architecture review gates) that the
|
||||
boundary costs more than containment saves.
|
||||
- Revisit if the platform grows additional data stores or engines (shared with
|
||||
the ADR-005 revisit trigger): a second engine may need its own contained
|
||||
adapter, and the query-builder containment rule would extend per adapter.
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# ADR index (§70)
|
||||
|
||||
Repository copy of the ADR index from the wiki ADR-Index page (§70): the
|
||||
canonical list of architectural decisions, committed or planned. Every ADR
|
||||
committed to `docs/adr/` must record a decision that matches its row in
|
||||
section 70; the wiki page remains the canonical index.
|
||||
|
||||
| ADR | Decision |
|
||||
|---|---|
|
||||
| ADR-001 | Modular monolith |
|
||||
| ADR-002 | Node.js 24 LTS runtime |
|
||||
| ADR-003 | TypeScript 6.0.3 pending TS7.1 ecosystem review |
|
||||
| ADR-004 | Fastify 5 HTTP runtime |
|
||||
| ADR-005 | PostgreSQL 18 sole canonical DB |
|
||||
| ADR-006 | Kysely contained inside DB adapter |
|
||||
| ADR-007 | React SSR for public rendering |
|
||||
| ADR-008 | React/Vite admin |
|
||||
| ADR-009 | Zero-JS public baseline |
|
||||
| ADR-010 | Client-island model for optional public interactivity |
|
||||
| ADR-011 | JSON Schema + TypeBox + Ajv validation |
|
||||
| ADR-012 | EPPP Extension API hides framework internals |
|
||||
| ADR-013 | Node/Amber is a theme extension |
|
||||
| ADR-014 | Blog is a first-party content extension |
|
||||
| ADR-015 | Versioned block documents |
|
||||
| ADR-016 | Versioned page composition |
|
||||
| ADR-017 | Extension-owned migrations/tables |
|
||||
| ADR-018 | Docker Compose primary installation |
|
||||
| ADR-019 | Opaque DB-backed admin sessions |
|
||||
| ADR-020 | Separate anonymous preference identity |
|
||||
| ADR-021 | Local media storage through storage port |
|
||||
| ADR-022 | PostgreSQL jobs before external broker |
|
||||
| ADR-023 | No Redis initially |
|
||||
| ADR-024 | No microservices initially |
|
||||
| ADR-025 | Trusted build-time executable extensions in v1 |
|
||||
| ADR-026 | Exact dependency pinning + controlled upgrade lanes |
|
||||
| ADR-027 (v1.1) | `core.markdown` block restores Markdown authoring inside the block model |
|
||||
| ADR-028 (v1.1) | Hardened outbound fetch as a core service; extensions never fetch directly |
|
||||
| ADR-029 (v1.1) | Embed provider allowlist enforced in renderer and generated CSP |
|
||||
| ADR-030 (v1.1) | Native server-side SVG charts and diagrams with an accessibility contract |
|
||||
| ADR-031 (v1.1) | Theme renaming replaces trademark references |
|
||||
| ADR-032 (v1.1) | Day-one byte budgets; latency targets from measurement |
|
||||
|
||||
Every ADR contains: Context, Decision, Alternatives, Consequences, Operational
|
||||
impact, Revisit trigger (§46 E01-S01).
|
||||
|
||||
## Architectural fitness tests (§71)
|
||||
|
||||
- **Add Ledger/Paper:** create `theme-paper` extension → register
|
||||
manifest/tokens/assets → optionally override renderer slots → tests →
|
||||
include in build. Failure = editing Home/Post domain, core DB, auth, or
|
||||
`if (theme === "paper")` in core.
|
||||
- **Add Reading:** create `org.eppp.reading` → migrations → public route →
|
||||
admin contribution → Home section → settings → job(s) → content/block
|
||||
contributions. Failure = core learning seam/half-life/bookmark/link-health
|
||||
semantics.
|
||||
|
||||
## Architecture review gates (§68)
|
||||
|
||||
Gate A (end Sprint 1): publish a real post without core becoming
|
||||
blog/Amber-specific. Gate B (end Sprint 3): add a Home feature as an extension
|
||||
with no core edits. Gate C (end Sprint 4): a radically different theme runs
|
||||
without changing content/business logic. Gate D (end Sprint 5): visitor
|
||||
preference persists without coupling to auth or theme storage. Gate E (before
|
||||
public SDK): Extension API v1 proven enough to maintain. Gate F (Reading):
|
||||
Reading owns its whole domain without `if (readingEnabled)` in core.
|
||||
Reference in New Issue
Block a user