Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/scripts/test_ci_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ def test_docs_only_change_skips_rust(self) -> None:
self.assertTrue(outputs["docs"])
self.assertFalse(outputs["docs_archives"])

def test_architecture_model_changes_run_docs_checks(self) -> None:
for path in (
"docs/site/architecture/likec4.config.json",
"docs/site/architecture/model/runtime.c4",
"docs/site/architecture/tests/architecture-model.test.mjs",
):
with self.subTest(path=path):
outputs = classify(self.workspace, (path,))
self.assertFalse(outputs["rust"])
self.assertTrue(outputs["docs"])
self.assertFalse(outputs["docs_archives"])

def test_archive_content_is_immutable_during_routine_docs_changes(self) -> None:
current_content = classify(
self.workspace,
Expand Down
7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ cargo check --locked --workspace --all-targets
cargo test --locked -p <changed-crate> # then the workspace if platform crates changed
```

In Codex-managed worktrees, invoke Cargo through `scripts/cargo-codex`. The

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required DCO sign-off

The reviewed commit has no Signed-off-by trailer (git interpret-trailers --parse returns no trailers), so it does not satisfy the repository's mandatory DCO policy and cannot pass the contribution gate. Recreate the commit with git commit -s or otherwise add a valid sign-off before merging.

AGENTS.md reference: AGENTS.md:L75-L77

Useful? React with 👍 / 👎.

wrapper disables incremental compilation and development/test debug info, then
normalizes worktree paths for the shared bounded `sccache`. During iteration,
run crate-scoped checks and tests. Run workspace-wide check, clippy, and tests
once before finalizing when the changed trust boundary requires them. Do not use
`--all-features` unless the change specifically requires it.

Root CI's `rust` job runs `cargo fmt --check`, `cargo check --locked
--workspace --all-targets`, `cargo clippy --workspace --all-targets --
-D warnings`, `cargo test --locked --workspace`, the full `cargo deny check`
Expand Down
27 changes: 27 additions & 0 deletions docs/site/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,33 @@ npm run dev
npm run check
```

## Explore the architecture model

`architecture/` contains an experimental LikeC4 model of the stable cross-product architecture.
It includes complete context-to-code zoom paths for Registry Relay and Registry Notary, plus
portfolio, dynamic, and deployment views.
The model supplements the narrative pages and existing accessible SVGs. It is not published with
the Starlight site. Its [review contract](architecture/README.md) defines the C4 scope, evidence
requirements, executable checks, visual review, and maintainer sign-off.

Start the local explorer:

```sh
npm run architecture:dev
```

Validate the model, evidence references, source hygiene, C4 scope, and cross-product boundary
invariants:

```sh
npm run check:architecture
```

LikeC4 is pinned to `1.38.1` to preserve the repository's Node.js 22.12.0 contract.
The Playwright override selects the first release that fixes
[GHSA-7mvr-c777-76hp](https://github.com/advisories/GHSA-7mvr-c777-76hp).
The pilot does not use Playwright-based image exports.

The check command validates frontmatter, generated data, Markdown structure,
prose style, OpenAPI snapshots, SVG accessibility, Astro types, the static
build, and generated Redoc API pages. It checks the current site only. Published
Expand Down
98 changes: 98 additions & 0 deletions docs/site/architecture/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Registry Stack architecture model

This experimental LikeC4 model records stable cross-product boundaries and selected
implementation-level zoom paths.
It supplements the narrative documentation and specifications.
The source code, tests, OpenAPI documents, and RS requirements remain the sources of truth.

## Scope and C4 levels

The model contains two complete C4 zoom paths for the runtime products.
Do not infer lower-level structure for Registry Manifest or Registry Platform from their
portfolio boxes.
Use the official [C4 diagram definitions](https://c4model.com/diagrams) when classifying a new view.

| View | Diagram type | C4 status | Review question |
| --- | --- | --- | --- |
| `relayContext`, `notaryContext` | System context | C4 level 1 | Are the people, systems, and external responsibilities around one product correct? |
| `relayContainers`, `notaryContainers` | Container | C4 level 2 | Are the executable processes, data stores, protocols, and ownership boundaries correct? |
| `relayComponents`, `notaryComponents` | Component | C4 level 3 | Do the in-process responsibilities and security gates match the source structure? |
| `relayProtectedReadCode`, `notaryIssuanceCode` | Code | C4 level 4, selected slices | Do the named Rust symbols preserve the security-critical ordering and boundaries? |
| `index` | Portfolio overview | C4-adjacent, not a strict system landscape | Are product, tooling, adopter, and decision boundaries correct? |
| `protectedRegistryApi` | Dynamic | Software-system interaction | Does a protected Relay read preserve source, minimization, and audit boundaries? |
| `registryBackedIssuance` | Dynamic | Software-system interaction | Does issuance retain the exact Relay-backed provenance boundary? |
| `delegatedEvaluation` | Dynamic | Software-system interaction | Does the view show only the shipped inbound federation capability? |
| `singleNodeDeployment` | Deployment | Software-system instances and infrastructure | Does the documented production target keep product state and dependencies separate? |

Registry Relay and Registry Notary are modeled as C4 software systems.
Registry Manifest is an offline application, and Registry Platform is a supporting library.
That mixed portfolio is why `index` is not labeled as a C4 system landscape.

The Relay path zooms from the software system into its server and PostgreSQL store, then into the
server components, and finally into the protected-read code that preserves governed and
principal-bound query gates.
The Notary path zooms into the corresponding runtime and store, then into evaluation,
consultation, issuance, federation, and audit components, and finally into the code that refuses
credential issuance without exact stored Relay provenance.

The code views are intentionally small.
They name selected Rust symbols instead of reproducing the crate graph, and the tests verify that
each symbol still exists in its evidence file.
Add another code view only when one component has a security, maintenance, or onboarding question
that a source link alone does not answer.

## Correctness contract

Architecture correctness has four independent gates:

1. Source evidence: every logical element and relationship names a repository path or RS
requirement.
2. Executable semantics: the Node tests query the computed LikeC4 model and pin product,
source-access, issuance, federation, decision, audit, signing, and deployment-state boundaries.
3. Rendered review: a reviewer opens all 13 views and checks labels, nesting, edge direction,
density, and merged relationships.
4. Maintainer judgment: security, trust, and privacy claims require Tier-C source-pack sign-off
before merge.

`likec4 validate` proves syntax and model consistency.
It does not prove that a claim matches shipped behavior, that a C4 level is appropriate, or that a
rendered diagram is readable.

## Review a change

Install and run the model gate:

```sh
npm ci
npm run check:architecture
```

For dependency changes, also run:

```sh
npm audit
```

Open the explorer:

```sh
npm run architecture:dev
```

Review every view at the default browser width.
Reject a change when a node is unconnected without an explicit reason, an edge direction does not
match the actor, a label implies behavior not present in source, a boundary mixes C4 levels without
being declared as a portfolio view, a scoped C4 view contains elements below its declared level,
or the diagram depends on unreadable zoom.

Then run the complete docs gate:

```sh
npm test
npm run check
```

The pull request description must name the implementation evidence reviewed for changed behavior
claims.
For a deployment target, it must also say whether the diagram represents shipped generated
artifacts, a verified production topology, or documented target guidance.
9 changes: 9 additions & 0 deletions docs/site/architecture/likec4.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://likec4.dev/schemas/config.json",
"name": "registry-stack",
"title": "Registry Stack architecture",
"metadata": {
"owner": "registry-docs",
"status": "experimental"
}
}
70 changes: 70 additions & 0 deletions docs/site/architecture/model/deployments.c4
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
deployment {
environment singleNode 'Single-node production target' {
#targetTopology

metadata {
evidence 'docs/site/src/content/docs/operate/single-node-compose-behind-proxy.mdx'
}

trustBoundary institution 'Institution-operated boundary' {
host edge 'Public edge host or service' {
edgeProxy = instanceOf reverseProxy
}

host applicationHost 'Single application host' {
network runtime 'Private runtime network' {
relay = instanceOf registryStack.relay.server

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Model separate public and consultation Relay lanes

When this view is used as the documented single-node production target, this single Relay instance receives both edge traffic and the Notary consultation relationship, but the cited deployment guide explicitly requires one public Relay and one private consultation Relay (single-node-compose-behind-proxy.mdx:24-29). Collapsing them erases a deployment and trust boundary that the architecture model is intended to preserve; represent the two Relay instances separately and associate each lane with its corresponding state and traffic.

AGENTS.md reference: docs/site/AGENTS.md:L25-L28

Useful? React with 👍 / 👎.

notary = instanceOf registryStack.notary.server
}

network data 'Private data and state network' {
sourceMount = state 'Registry source mount or private binding'
relayState = instanceOf registryStack.relay.correctnessState
notaryState = instanceOf registryStack.notary.correctnessState
Comment on lines +20 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include durable anti-rollback state in the target

When operators use this as the documented production target, the data network shows only the two PostgreSQL correctness stores, while the cited deployment guide separately requires durable storage for PostgreSQL and for each product's anti-rollback state (single-node-compose-behind-proxy.mdx:44). Because neither modeled datastore includes anti-rollback state, the diagram presents an incomplete persistence boundary that could lead an implementation to omit the files needed for safe startup and upgrades; add the per-product anti-rollback stores explicitly.

AGENTS.md reference: docs/site/AGENTS.md:L25-L28

Useful? React with 👍 / 👎.

}
}

trustBoundary services 'Institution-managed dependencies' {
signing = instanceOf keyProvider
audit = instanceOf auditDestination
identity = instanceOf identityProvider
}

edge.edgeProxy -> applicationHost.runtime.relay 'Forwards public Relay traffic' {
metadata {
evidence 'docs/site/src/content/docs/operate/single-node-compose-behind-proxy.mdx'
}
}
edge.edgeProxy -> applicationHost.runtime.notary 'Forwards public Notary traffic' {
metadata {
evidence 'docs/site/src/content/docs/operate/single-node-compose-behind-proxy.mdx'
}
}

applicationHost.runtime.relay -> applicationHost.data.sourceMount
'Reads the reviewed source binding' {
metadata {
evidence 'REQ-ARC-G-006'
}
}
applicationHost.runtime.relay -> applicationHost.data.relayState
'Persists consultation correctness state' {
metadata {
evidence 'docs/site/src/content/docs/operate/retention-and-persistent-state.mdx'
}
}
applicationHost.runtime.notary -> applicationHost.data.notaryState
'Persists transaction, replay, evaluation, issuance, and status correctness state' {
metadata {
evidence 'REQ-ARC-G-013'
}
}
applicationHost.runtime.notary -> applicationHost.runtime.relay
'Executes a compiler-pinned consultation over the private runtime network' {
metadata {
evidence 'crates/registry-notary-server/src/relay_client.rs'
}
}
}
}
}
94 changes: 94 additions & 0 deletions docs/site/architecture/model/externals.c4
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
model {
caller = externalSystem 'Caller system' {
#external

description 'Technical client that invokes Relay or Notary'

metadata {
evidence 'docs/site/src/content/docs/explanation/architecture.mdx'
}
}

evidenceConsumer = externalSystem 'Evidence consumer' {
#external

description 'System that uses returned evidence under its own policy'

metadata {
evidence 'docs/site/src/content/docs/explanation/architecture.mdx'
}
}

decisionOwner = actor 'Decision owner' {
#external, #decisionBoundary

description 'Accountable authority for requirements, eligibility, workflow, and action'

metadata {
evidence 'docs/site/src/content/docs/explanation/architecture.mdx'
}
}

registrySource = externalSystem 'Registry source' {
#external

description 'Authoritative source system that retains operational records'

metadata {
evidence 'REQ-ARC-G-001,REQ-ARC-G-002,REQ-ARC-G-006'
}
}

identityProvider = externalSystem 'Identity provider' {
#external, #optional

description 'Optional issuer for an OpenID Connect deployment'

metadata {
evidence 'crates/registry-platform-oidc/src/lib.rs'
}
}

keyProvider = externalSystem 'Signing provider' {
#external
Comment on lines +52 to +53

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep local signing inside the Notary boundary

In the documented single-node target, Notary consumes an operator-supplied private JWK (single-node-compose-behind-proxy.mdx:120-124), and the cited implementation builds LocalJwkEnv signers inside SigningKeyRegistry; it is not an external software system. Modeling every signing provider as externalSystem and instantiating it under institution-managed dependencies therefore invents a separate runtime/custody boundary for the default target. Represent the local signer inside Notary and reserve an external dependency for configurations such as an actually remote key provider.

AGENTS.md reference: docs/site/AGENTS.md:L25-L28

Useful? React with 👍 / 👎.


description 'Configured provider for Notary signing key operations'

metadata {
evidence 'crates/registry-notary-server/src/standalone/signing/providers.rs'
}
}

auditDestination = externalSystem 'Audit pipeline' {
#external

description 'Configured audit sink or operator-owned shipping pipeline'

metadata {
evidence 'crates/registry-platform-audit/src/lib.rs'
}
}

peerNotary = externalSystem 'Trusted peer Notary' {
#external, #staticTrust

description 'Peer allowed to call the local inbound federation endpoint'

metadata {
evidence 'REQ-ARC-G-009'
replayScope 'peer-scoped'
runtimeIsolationGate 'absent'
trustDiscovery 'static-config'
}
}

reverseProxy = externalSystem 'Institutional reverse proxy' {
#external

description 'Deployment-owned public TLS, request admission, and front rate limiting'

metadata {
evidence 'docs/site/src/content/docs/operate/single-node-compose-behind-proxy.mdx'
}
}
}
Loading
Loading