Publish a Versioned AtlasModel for Search, APIs, and RAG
Superseded (2026-08-25).
adr.knowledge-api-servicedecided this differently: once the “Expose Ocean-Atlas Knowledge APIs” epic supplied the concrete consumer set this RFC’s own §7.1 said was missing (Ocean Studio, Ocean CLI, Ocean Assistant, generators, compiler diagnostics), Ocean-Atlas built a private runtime API overAtlasModelinstead of the static artifact proposed below. This RFC is kept as historical proposal context, perdecisions.rfcs.index’s lifecycle rules, and is not rewritten to describe the resulting implementation. Its static-artifact design remains a reasonable starting point if a future consumer needs an offline or build-time snapshot rather than a live API.
1. Summary
Section titled “1. Summary”builders/core already normalizes every canonical document and example
into a single, technology-independent AtlasModel at build time. Today
that model is an internal intermediate file, local to the
builders/astro-starlight adapter, undocumented, and unversioned as a
contract. This RFC proposes deriving a stable, schema-versioned public JSON
projection from that model. Search, a future Ocean-Atlas API, and future RAG
ingestion can consume the supported projection instead of scraping rendered
HTML or reimplementing Markdown parsing. Canonical Markdown remains the source
of truth; the published JSON is a reproducible distribution artifact.
2. Motivation
Section titled “2. Motivation”adr.search-today-structured-retrieval-tomorrow already decided that any
future retrieval or RAG system must consume Core’s structured model rather
than rendered presentation output. That decision assumes the model is
reachable by such a consumer. Today it is not: AtlasModel is written to
builders/astro-starlight/.generated/atlas-model.json, a gitignored,
adapter-local build artifact that only generate-content.mjs reads. A
current build produces a real, complete model — 67 documents, 9 examples,
7 navigation groups — but nothing outside that one build step ever sees
it.
Without a published, versioned artifact, every future consumer faces the
same choice this RFC exists to close off: either scrape the deployed site
(the anti-pattern adr.search-today-structured-retrieval-tomorrow
explicitly rejects), or write its own Markdown/metadata parser against the
canonical source (duplicating builders/core, with no guarantee of
staying consistent with it). Neither is acceptable once a second consumer
beyond the Astro adapter actually exists.
3. Goals
Section titled “3. Goals”- Define a versioned, documented JSON schema for a public projection of
AtlasModel. - Publish that artifact as part of the static build, at a stable, fetchable path, with no new runtime infrastructure.
- Give external consumers an explicit compatibility guarantee tied to
schemaVersion. - Keep the artifact technology-independent, matching the presentation
neutrality
adr.atlas-builder-boundaryalready requires of the model it is built from.
4. Non-Goals
Section titled “4. Non-Goals”- Not a runtime Atlas API or query service.
adr.atlas-builder-boundary§11 already excludes a runtime Atlas API from Core; this RFC proposes a static file produced at build time, not a live endpoint. - Not an embeddings, vector-store, or RAG-pipeline design. Those are downstream consumers of the artifact this RFC proposes; their design is out of scope here.
- Not a redesign of the glossary, patterns, or ADR content models. This RFC defines a distribution projection without restructuring how knowledge is authored or freezing Core’s internal TypeScript representation.
- Not real-time or incremental publishing. The artifact is republished once per site build, on the same cadence as the static site itself.
5. Current State
Section titled “5. Current State”builders/core’s AtlasModel (see builders/core/src/types.ts) already
has this shape:
export interface AtlasModel { schemaVersion: 1; documents: NormalizedDocument[]; examples: NormalizedExample[]; navigation: NavigationGroup[]; assets: NormalizedAsset[];}As of this writing, one build produces:
| Field | Current content |
|---|---|
documents |
67 normalized canonical documents |
examples |
9 normalized examples (Horizon, Voyage, and implementation-file inventory each) |
navigation |
7 top-level navigation groups |
assets |
always [] — NormalizedAsset is defined but nothing currently populates it |
This model is written once, to
builders/astro-starlight/.generated/atlas-model.json (about 1.15 MB
uncompressed today), consumed only by
builders/astro-starlight/scripts/generate-content.mjs, and is excluded
from version control and from the deployed dist/ output. No document in
Ocean-Atlas today describes its schema as a contract; the closest existing
description is the “Core V1 Contract” section of
adr.atlas-builder-boundary, which explicitly calls its TypeScript shapes
“illustrative,” not frozen.
6. Proposed Design
Section titled “6. Proposed Design”6.1 Publish location and cadence
Section titled “6.1 Publish location and cadence”Generate the public projection at the schema-versioned path
/api/atlas-model/v1.json so it deploys alongside the site through the
existing Fly.io pipeline, with no new hosting, service, or runtime component.
It is republished exactly when the site is rebuilt. Consumers use the
versioned path rather than an unversioned alias whose contract could change
silently.
6.2 Schema versioning
Section titled “6.2 Schema versioning”schemaVersion already exists on the type. This RFC proposes treating it
as the actual compatibility contract for external consumers: a
backward-compatible addition (a new optional field) does not require a
version bump; any change that removes or repurposes an existing field
does, and the previous version’s artifact remains available at its own
path for a defined deprecation window (window length is an open question —
see Section 12).
6.3 Document and example representation
Section titled “6.3 Document and example representation”Proposed for v1: derive explicit public document and example records rather
than serializing Core’s internal objects unchanged. The projection includes
stable IDs, titles, summaries, type/area/status/authority metadata, routes,
authored document content, usage metadata, Horizon and Voyage explanation,
and typed relationships. It deliberately excludes internal sourcePath and
sourceDirectory fields.
The Implementation facet publishes a manifest containing relative path, kind,
media type, and content hash. Full implementation-file content is excluded
from v1 by default. Navigation may be included as a convenience projection;
empty internal placeholders such as today’s assets: [] are omitted until
they have a defined public purpose.
V1 deliberately does not attempt heading-level chunking or a
retrieval-optimized representation — per
atlas.knowledge-architecture §21.3 (“Chunking Readiness”), chunk
boundaries should follow logical knowledge boundaries, but no real
chunking consumer exists yet to validate what those boundaries should be.
Adding a chunk-aware representation is left as a candidate for a later
schema version, once a concrete consumer can validate it — consistent
with adr.atlas-builder-boundary’s principle of generalizing only what a
real consumer has proven necessary.
6.4 Relationship encoding
Section titled “6.4 Relationship encoding”Relationships are published as-is: { type, target } pairs referencing
stable IDs (adr.stable-knowledge-identity), not pre-resolved objects.
Consumers that want a fully resolved graph join target against
documents/examples themselves. This keeps the artifact’s size and
generation cost independent of how deeply consumers want to traverse
relationships.
6.5 Authority and status filtering
Section titled “6.5 Authority and status filtering”Publish every document that the public website publishes, regardless of
status or authority, and let the corresponding fields support filtering
on the consumer side. This matches
atlas.knowledge-architecture §21.5 (“Authority Awareness”), which
expects AI systems to distinguish authority levels. Content excluded from
the public website must not become public merely because it exists in Core.
6.6 Example content
Section titled “6.6 Example content”Examples’ implementation.files already inventories implementation files and
can carry readable file content internally. The public v1 projection includes
only the implementation manifest, not those full contents. A later proposal
may define a separate, deliberately reviewed source distribution if a real
consumer requires it.
7. Alternatives Considered
Section titled “7. Alternatives Considered”7.1 Build a runtime query API instead of a static artifact
Section titled “7.1 Build a runtime query API instead of a static artifact”Rejected for this proposal. A live API is a larger infrastructure
commitment — hosting, availability, versioning of a running service — than
is justified before any concrete consumer exists, and
adr.atlas-builder-boundary already scoped a runtime Atlas API out of
Core V1 for the same reason. A static, versioned artifact can still be the
foundation such an API is built on later.
7.2 Let each consumer invoke builders/core’s TypeScript API directly
Section titled “7.2 Let each consumer invoke builders/core’s TypeScript API directly”Considered. This works for a Node.js-based consumer inside this repository’s toolchain, but not for an external tool, a non-JavaScript RAG pipeline, or any consumer that shouldn’t need to clone Ocean-Atlas and run its build to get the model. A portable, published artifact serves both cases; a TypeScript-only API serves neither by itself.
7.3 Continue as-is: adapter-local, unpublished, undocumented
Section titled “7.3 Continue as-is: adapter-local, unpublished, undocumented”Rejected — this is the status quo this RFC exists to change. It leaves
adr.search-today-structured-retrieval-tomorrow’s “must consume Core’s
structured model” constraint with no way for an external consumer to
actually do so.
7.4 Publish one JSON file per document instead of one combined model
Section titled “7.4 Publish one JSON file per document instead of one combined model”Considered. Per-document files would give smaller individual payloads and possibly simpler caching, but would lose the pre-computed navigation and would multiply the number of requests needed to reconstruct the graph. This RFC proposes the single combined artifact for v1 and leaves per-document publishing as an open question rather than resolving it.
8. Compatibility and Migration
Section titled “8. Compatibility and Migration”No existing external consumer reads today’s adapter-local
.generated/atlas-model.json, so introducing a separate public projection is
additive. No canonical document, ID, or route changes as a result. Core’s
internal model may continue evolving independently as long as the projection
preserves its documented v1 contract.
9. Security and Privacy
Section titled “9. Security and Privacy”- Private submodule content. Full implementation-file content is excluded from v1. Only the public example explanation, usage metadata, and a non-sensitive implementation manifest are included.
- Repository paths. Internal
sourcePathandsourceDirectoryvalues are excluded. Public routes and implementation-relative paths provide the identifiers consumers actually need. - No new authentication surface. This proposal adds a static file to an already-public static site; it does not add a new authenticated endpoint, so it does not introduce a new access-control surface to design.
10. Operational Considerations
Section titled “10. Operational Considerations”- Size and growth. The current internal model is approximately 1.15 MB uncompressed for 67 documents and 9 examples. The proposed projection should be smaller because it excludes implementation contents and internal paths. Its actual compressed and uncompressed sizes must be measured during rollout and revisited if they grow by an order of magnitude.
- Build cost. The internal model is already computed on every build. The additional projection, schema validation, and file write should remain small, deterministic build-time work and must not introduce runtime cost.
- Failure modes. If model normalization fails, the existing build
already fails before presentation generation (
adr.atlas-builder-boundary§18); this proposal does not change that behavior, so a broken model cannot be published as a “successful” artifact. - Observability. No new runtime service means no new uptime or latency monitoring surface; the only new operational signal is whether the artifact was published and is fetchable after each deploy, which can be a build-time check rather than a runtime one.
11. Validation and Acceptance Criteria
Section titled “11. Validation and Acceptance Criteria”- The published artifact’s schema is documented (this RFC or a successor reference document), including which fields are guaranteed stable.
- The artifact is fetchable at a stable, documented path from the deployed site.
schemaVersionis verified to change whenever a breaking shape change is introduced, and a compatibility/deprecation policy for prior versions is written down.- Automated validation proves that prohibited internal paths and implementation-file contents are absent from the artifact.
- At least one real consumer (even a simple validation script or the
existing
builders/coreaudit) reads the published artifact end to end as proof it is usable outside the adapter that produces it.
12. Open Questions
Section titled “12. Open Questions”- What is the deprecation window for a superseded
schemaVersion? - Should the artifact be one combined file or split (for example, by area, or one file per document)?
- Does chunk-aware document representation belong in a near-term schema version, or should it wait for a real RAG consumer to validate the approach, as proposed in Section 6.3?
- Who is the artifact’s intended audience for v1 — internal tooling only, or external third parties from day one — and does that change the answer to any of the questions above?
- Should a separately reviewed example-source artifact be proposed later, or is the implementation manifest sufficient for foreseeable consumers?
13. Rollout Plan
Section titled “13. Rollout Plan”- Resolve the remaining open questions in Section 12 through review of this RFC.
- Document the accepted schema as a reference document, and record the decision in an ADR (per this repository’s practice of recording accepted RFCs as ADRs).
- Add an explicit public-projection step to the Astro/Starlight build,
writing the artifact into
dist/api/atlas-model/v1.json. - Validate the published artifact against at least one real consumer
before treating
schemaVersion: 1as stable. - Only after a stable, consumed v1 exists, consider the deferred questions in Section 6.3 (chunk-aware representation) as a scoped follow-up proposal.
14. Related Knowledge
Section titled “14. Related Knowledge”adr.search-today-structured-retrieval-tomorrow— the decision this RFC makes concretely actionable: future retrieval must consume Core’s structured model, which today has no published, fetchable form.adr.atlas-builder-boundary— the Core/adapter boundary and the “Core V1 Contract” this RFC proposes to publish and version formally.adr.canonical-markdown-build-model— the build pipeline that produces the model this RFC proposes to export.adr.stable-knowledge-identity— the ID stability the published artifact’s relationship encoding depends on.adr.external-examples-repository— the private-repository boundary that requires the public projection to omit implementation-file contents.atlas.knowledge-architecture— §21 “AI and RAG Readiness,” which this proposal is a concrete step toward.
These semantic relationships are declared in the document metadata.