Fountain Coach Gitowner-controlled · read only

book-library.git · PLANS.md

book-library.git / PLANS.md

revision 6e4ff99f2303d50b6895464fa3aa955d9639c1c9 · complete file

## Released Book Library client boundary — FountainStore admission slice

Goal: expose the provider's existing public read contract as a reusable Swift `BookLibraryClientKit` library so a
host can fetch a pinned publication and admit it into FountainStore without starting a second provider service in
the request path.

Scope: typed read-only client for health, catalog, search, manifest, chapters, and source; injected transport for
deterministic tests; no provider mutation, persistence implementation, credentials, or URL guessing.

Validation: `swift test`, `git diff --check`, and a clean SemVer release consumed by the FountainStore integration.

## FountainMaintenanceKit server adapter — initial vertical slice

Goal: Consume the published FCIS Kit in the Book Library server and expose a narrow typed maintenance admission/read
surface with server-owned authorization and repeat-safe receipts.

Scope: remote Kit dependency, `MaintenanceAdmission`, health operation, operation receipt lookup, focused tests, and
fixture-server proof.

Non-goals: native Swift Git backend, deployment/promotion executors, real SecretStore provider, TLS termination,
remote production deployment, Reframe UI, or FountainStore integration.

Constraints: no secret values; no guessed SSH or filesystem authority; unsupported operations fail visibly.

Plan:
- Step 1 (status: completed) - Resolve published `FountainMaintenanceKit` and add the server admission adapter.
- Step 2 (status: completed) - Add authorization, idempotency, collision, and receipt tests.
- Step 3 (status: completed) - Run the fixture server and prove health success, retry, denial, receipt retrieval, and
  restart persistence.
- Step 4 (status: completed) - Commit and push the Book Library server adapter; record the exact Kit revision.

Validation:
- `swift test`
- fixture server HTTP proof on `/v1/maintenance/operations`
- `git diff --check`

Evidence:
- `FountainMaintenanceKit@0.1.1` revision `3d58c56bf5b685ea8211a0ec503317b1a74552eb`
- `swift test`: 13 tests passed
- Live fixture server: health `200/succeeded`, idempotent retry `200/same receipt`, unauthorized actor `403`, receipt
  lookup `200/succeeded`, and after process restart receipt lookup again returned `200/succeeded` with the same
  operation timestamp and identity.

## Durable maintenance receipts — Chapter 62/63 follow-on

Goal: make maintenance admission survive service restart without putting secrets or host-bound state into receipts.

Implemented: `MaintenanceAdmission` now writes typed request/receipt entries atomically beneath the explicit
`BOOK_LIBRARY_MAINTENANCE_RECEIPTS_ROOT`; a new process reloads by idempotency key and operation ID. Unsafe keys,
unknown actors, and idempotency collisions fail closed.

Non-goals: deployment executor, native Git, real SecretStore authentication, or remote production rollout.

Validation: 13 Book Library tests plus live stop/restart/receipt lookup proof passed.

## Server-side maintenance authentication — Chapter 63 follow-on

Implemented: `MaintenanceBearerAuthenticator` verifies the SHA-256 digest configured by
`BOOK_LIBRARY_MAINTENANCE_TOKEN_SHA256`. When configured, both maintenance POST and receipt GET routes require an
exact bearer credential; the raw token is never persisted, logged, or placed in a receipt. An absent digest is
explicitly reported as fixture-only mode and is not a production deployment claim.

Validation: 14 Book Library tests passed. Live configured-server proof returned `401` for a wrong bearer, `200` and a
succeeded receipt for the correct bearer, and a receipt lookup containing no token or authorization value.

## Production binding and atomic code rollout — Chapter 63 follow-on

Added reviewed, explicit-apply deployment helpers for the fixed `library.fountain.coach` publication tuple. The
verifier is provisioned separately from the code rollout and accepts only a SHA-256 digest on stdin. The code
deployer requires a clean, exact commit, transfers an archive with a local digest check, builds an immutable release
on the host, switches `current` atomically, verifies health, and restores the prior release on failure. No raw
credential is stored in the repository, archive, service receipt, or command argument.

Acceptance remains open until the current Reframe commit is deployed, the verifier is configured, and an authenticated
`maintenance.health.verify` operation produces a typed receipt through Reframe.

## Image Cloud maintenance executor — Phase 6 (2026-08-13)

Goal: close the deployment seam for the released portable Image Cloud executable without introducing arbitrary remote
shell execution into the maintenance API.

Chapters read: Reframe 07/08/62/63/66 — plan against actual code; use typed authenticated requests; keep release
identity, authorization, idempotency, rollback, and migration explicit; keep Image Cloud bytes server-side.

What they forbid here: accepting arbitrary paths or commands from a request, treating an admitted receipt as a deploy,
switching a release without verification, or exposing service credentials in receipts or logs.

Conflict: the original maintenance slice declared deployment execution a non-goal, while the current hosted Image
Cloud phase requires it. This phase narrows the new authority to an allowlisted `image-cloud` release executor and
records the former non-goal as superseded.

Excluded: Git discovery, DNS changes, arbitrary service control, credential values, and deployment of any target other
than the explicitly configured Image Cloud service.

## Image Cloud public route — Phase 7 (2026-08-17)

The hosted Image Cloud executable was active on `127.0.0.1:8788`, but the public Caddy host routed `/v1/assets/*` to
Book Library on `8787`. The reviewed `Deploy/provision-image-cloud-route.sh` helper now owns this exact route change;
it validates Caddy, reloads it, requires the unauthenticated intake probe to return `401` rather than `404`, and
restores the prior configuration on any failure. It is scoped only to `library.fountain.coach` and `127.0.0.1:8788`.