The foundation of the hosted registry, in canned-prompts so rapp.yaml gets ownership_repo: canned-prompts — the sbom-nexus shape, where product ownership stays out of the operations repo. Stack matches state-hub and sbom-nexus: FastAPI, SQLAlchemy, Alembic, PostgreSQL, in service/ with its own environment. reference/ is deliberately untouched: it is the format's conformance witness and stays dependency-light, and the service is a separate consumer of the same package semantics. CANNED_PROMPTS_DATABASE_URL has no default. A service that silently falls back to a local database when its real one is misconfigured is worse than one that refuses to start. Health surface per RailianceAppDeploymentGuide.md: unauthenticated /healthz and /readyz, plus /state/health for fleet consistency. /healthz deliberately checks nothing beyond the process being up, so a database blip does not restart pods; /readyz asks the database something it can fail to answer. Migration 0001 creates package_versions, package_files and index_entries, every one carrying a tenant key per business-app-service-contract section 1.3 — the service is single-tenant today, and the key is present so a later consolidation is a data copy rather than a rewrite. A test asserts every table in the metadata is tenant-keyed, so adding an unkeyed table fails the suite rather than being discovered at consolidation time. Uniqueness is (tenant, registry, package_id, version): registry-scoped because identity is, tenant-scoped so two tenants may hold the same id. The schema keeps the format's three things distinct — an immutable package version, its files as content rather than parsed rows, and an index entry recording how a version arrived here. Fixes a bug its own test caught: check_readiness first caught every failure in one except and reported "database unreachable", so an unmigrated but perfectly reachable database sent an operator to credentials and networking when the fix was alembic upgrade. Connectivity and schema are now checked separately. Service tests 11 passing; reference tests unaffected at 99. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bjefh8NUiEiahN4JLwoSKM Assistant: claude-code Assistant-Model: opus Assistant-Process: 388925@bnt-lap001 Assistant-Session: 3507023f-e0fd-4a1e-9d90-a0d4217d1502 |
||
|---|---|---|
| .. | ||
| migrations | ||
| src/canned_prompts_service | ||
| tests | ||
| alembic.ini | ||
| pyproject.toml | ||
| README.md | ||
canned-prompts service
The hosted registry and index (CANP-WP-0006). Product ownership lives here
alongside the specification and the reference CLI; deployment and operation will
belong to rapp-canned-prompts once there is an image digest to pin.
This service hosts packages. It does not execute them — INTENT.md's
deliberate boundary holds, so rendering stays deterministic and a derive
default remains a declaration the service does not satisfy.
reference/ is deliberately untouched by this. It is the format's conformance
witness and stays dependency-light; the service is a separate consumer of the
same package semantics.
Stack
FastAPI, SQLAlchemy, Alembic, PostgreSQL — matching state-hub and
sbom-nexus.
cd service
uv venv && uv pip install -e ".[dev]"
.venv/bin/python -m pytest -q
export CANNED_PROMPTS_DATABASE_URL=postgresql+psycopg://...
.venv/bin/alembic upgrade head
.venv/bin/uvicorn canned_prompts_service.api:create_app --factory
CANNED_PROMPTS_DATABASE_URL has no default. A service that silently falls
back to a local database when its real one is misconfigured is worse than one
that refuses to start.
Health surface
RailianceAppDeploymentGuide.md requires unauthenticated /healthz and
/readyz; /state/health matches the rest of the fleet.
| Endpoint | Answers | Fails when |
|---|---|---|
/healthz |
is the process up | never — deliberately checks nothing else, so a database blip does not restart pods |
/readyz |
can it serve | no database configured, unreachable, or schema not migrated |
/state/health |
fleet-shaped status | same as /readyz, reported as degraded |
Connectivity and schema are checked separately. Both mean not-ready, but they send an operator to different places — credentials and network, or an unrun migration — so collapsing them into one message would send people to the wrong one.
Tenancy
Every table holding owned data carries a tenant key from migration 0001,
per business-app-service-contract_v0.1 § 1.3. The service is deployed
single-tenant today; the key is present so a later consolidation is a data copy
rather than a rewrite, and no query may assume it is the only tenant (§ 1.4).
Uniqueness is (tenant, registry, package_id, version) — registry-scoped
because identity is (§ 3.2), and tenant-scoped so two tenants may legitimately
hold the same id.
Schema
| Table | Holds |
|---|---|
package_versions |
one immutable <registry>:<id>@<version>, its manifest, and indexed discovery fields |
package_files |
the package's files as content, not parsed into rows |
index_entries |
how a version arrived here (§ 20.3): source, method, included_at never overwritten, last_seen_at |
Status
CANP-WP-0006 T01 and T02 are done: skeleton, health surface, tenant-keyed
schema and migration 0001. The read API, publish API, HTTP registry client and
container image (T03–T06) are not built yet.