Skip to content

Latest commit

 

History

History
1902 lines (1343 loc) · 46.3 KB

File metadata and controls

1902 lines (1343 loc) · 46.3 KB

k2atlas

k2atlas is the definition-driven engine for structured listings.

It exists to provide one common data model for many listing types that have different domain payloads but the same outer shell and operational behavior.

Examples:

  • hotel listing
  • room listing
  • book listing
  • book-series listing
  • dating profile listing
  • car listing

See also k2atlas/LISTING_MODEL.md for a sharper definition of the canonical listing object, sublisting model, and standard read projections.

Purpose

k2atlas exists to solve the repeated complexity around structured listings once, generically, instead of rebuilding it inside each product.

The trivial part is storing a record and reading it back.

The hard part is everything around it:

  • slug rules and stable URL identity
  • media ingestion
  • hero image selection
  • gallery management and ordering
  • structured sections
  • publication state
  • ranking and weighting
  • taxonomy
  • locality and containment
  • one-to-many composition
  • variants and child listings
  • filtering
  • aggregation
  • list-card and detail-page composition
  • editorial curation
  • search indexing
  • duplication and canonicalization
  • permissions and workflow

These pressures recur across many domains even when the payload differs.

Examples:

  • dating profile
  • hotel
  • room type
  • restaurant
  • beach
  • excursion
  • car rental
  • business profile
  • marketplace item

The domain-specific fields vary, but the surrounding listing structure is largely the same.

Product Boundary

k2atlas is not:

  • raw storage
  • authentication
  • authorization
  • messaging
  • page rendering
  • a generic CMS blob store
  • a page builder
  • a generic graph engine

k2atlas is the shared listings model that turns typed listing definitions into canonical, filterable, rankable, render-ready records.

Within the wider platform:

  • k2db persists canonical listing records and projections
  • k2login authenticates actors
  • k2rbac authorizes listing and workflow operations
  • k2mx emits and consumes lifecycle events
  • k2atlas defines listing kinds, common shell fields, composition rules, and derived read surfaces

Core Thesis

The abstraction is not that many internet objects happen to share a few fields.

The abstraction is that many internet listings are instances of the same operational form: a structured listing that must be published, surfaced, filtered, composed, ranked, and acted upon.

k2atlas should model the invariant shell of publishable listings, while domain definitions supply only the variable payload.

Canonical Core

The canonical core must stay small and invariant.

If it becomes a giant optional-field union, the system collapses back into a weak blob model.

The first-pass canonical listing record is AtlasEntity with the following top-level structure:

  • id
  • kind
  • slug
  • title
  • summary
  • media
  • sections
  • taxonomy
  • locality
  • visibility
  • lifecycle
  • actions
  • ordering
  • memberships
  • facets

Field Meanings

id

  • Stable canonical identity.

kind

  • Declared listing kind from contract data.
  • Examples: hotel, restaurant, dating_profile, room_type, beach.

slug

  • Stable human-facing URL identity for a listing.
  • May be unique globally or within a scope depending on package rules.

title

  • Primary human-facing label.

summary

  • Short human-facing description.

media

  • Canonical media attachments and ordering.
  • Main image, gallery, captions, crop intent, sort order, alternates.

sections

  • Structured content areas that make a listing renderable without becoming a freeform CMS.
  • Examples: overview, amenities, policies, specifications, highlights, editorial notes.

taxonomy

  • Explicit classifications.
  • Categories, tags, segments, themes, collections, editorial labels.

locality

  • Place semantics.
  • Country, region, city, area, coordinates, containment references, service radius.

visibility

  • Who can see the entity and under what conditions.

lifecycle

  • Draft, review, published, archived, revoked, scheduled, expired.

actions

  • What a consumer can do with the listing.
  • Examples: view, book, message, call, apply, buy, compare, visit, save.

ordering

  • Sort weight, boosted rank, pinned state, freshness inputs, editorial priority.

memberships

  • One-to-many composition.
  • Examples: hotel contains room types, series contains books, venue contains events.
  • Ordered membership is first-class where child order matters.

facets

  • Domain-specific payload through explicit typed facets only.

Contract Objects

The first implementation should treat the atlas model as a small set of explicit contract objects.

These objects are the listing-model surface that CUE definitions describe and that Rust validates, normalizes, stores, and projects.

AtlasEntity

AtlasEntity is the canonical listing record.

It represents a discoverable, publishable listing with stable identity and typed structure.

Conceptual shape:

AtlasEntity {
	id: EntityId
	kind: KindId
	title: LocalizedText
	summary?: LocalizedText
	media?: MediaSet
	taxonomy?: TaxonomySet
	locality?: LocalityRefSet
	visibility: VisibilityPolicy
	lifecycle: LifecycleState
	actions?: [Action]
	ordering?: OrderingPolicy
	relations?: [Relation]
	memberships?: [Membership]
	correspondences?: [Correspondence]
	facets: FacetPayloadSet
	provenance?: Provenance
}

Required invariants:

  • every entity has exactly one canonical id
  • every entity has exactly one declared kind
  • every listing may only carry declared facets for its kind
  • every membership must satisfy the child/member rules declared by that kind
  • no undeclared top-level semantic fields may appear in canonical storage

Relation

Relation is an optional secondary typed edge between listings.

It may express supporting connection where the listing model needs it, but it is not the center of Atlas.

Conceptual shape:

Relation {
	type: RelationType
	source_id: EntityId
	target_id: EntityId
	target_kind: KindId
	direction: Direction
	cardinality?: Cardinality
	inverse?: RelationType
	role?: RoleId
	metadata?: ValueMap
}

Examples:

  • hotel located_in area
  • room type variant_of hotel
  • book written_by author
  • restaurant near beach

Required invariants:

  • a relation must always have a declared type
  • target kinds must satisfy the contract for that relation type
  • relation metadata must be schema-bound, not ad hoc
  • relations do not imply equality or substitution unless a correspondence declares that separately

Membership

Membership is the core one-to-many composition edge.

It is used when a listing includes exact child listings in a defined sequence or slot structure.

Conceptual shape:

Membership {
	type: MembershipType
	source_id: EntityId
	target_id: EntityId
	target_kind: KindId
	position: u32
	label?: string
	required?: bool
	metadata?: ValueMap
}

Examples:

  • series contains books in reading order
  • guide contains curated listings in editorial order
  • hotel presents room types in preferred display order

Required invariants:

  • memberships are ordered by explicit position, never by insertion accident
  • membership semantics are directional
  • duplicate positions are invalid unless the membership type explicitly allows ties
  • membership is composition, not loose relation

Correspondence

Correspondence is the typed mapping between entities that are related by sameness, versioning, substitution, fulfillment, or variant semantics.

It exists specifically to avoid naive equality.

Conceptual shape:

Correspondence {
	type: CorrespondenceType
	source_id: EntityId
	target_id: EntityId
	target_kind: KindId
	direction: Direction
	strength: CorrespondenceStrength
	metadata?: ValueMap
}

Examples:

  • purchased item fulfills public item
  • edition 2 supersedes edition 1
  • public listing public_variant_of conceptual work
  • commercial listing commercial_variant_of conceptual work

Required invariants:

  • correspondence must be explicit and typed
  • correspondence is not assumed to be symmetric
  • correspondence does not collapse canonical identity
  • source and target may be semantically linked while remaining operationally distinct

Object Responsibilities

The objects have different responsibilities and must not be conflated.

  • AtlasEntity defines the canonical thing
  • Relation defines typed semantic connection
  • Membership defines ordered composition
  • Correspondence defines typed non-identity mapping

This separation is necessary to model domains like hospitality, marketplaces, and publishing without collapsing everything into one edge model.

Shared Value Types

The contract objects depend on a small set of shared value types.

These types must be canonical, deterministic, and reusable across all kinds.

The first pass should define at least the following.

Identity Types

EntityId

  • stable canonical entity identifier
  • opaque to clients
  • globally unique within atlas

KindId

  • stable identifier for a declared entity kind
  • examples: hotel, room_type, author, book, series

RelationType

  • stable identifier for a declared semantic edge type

MembershipType

  • stable identifier for an ordered composition edge type

CorrespondenceType

  • stable identifier for a declared non-identity mapping type

RoleId

  • stable identifier for a role-bearing relation meaning
  • examples: lead_author, contributor, translator, editor, illustrator

Text And Localization Types

LocalizedText

  • canonical localized text object
  • should support explicit locale keys
  • must not rely on inferred language from content

Conceptual shape:

LocalizedText {
	default_locale: LocaleId
	values: {
		[locale: LocaleId]: string
	}
}

LocaleId

  • stable locale identifier such as en, en-GB, th, de

Media Types

MediaAssetRef

  • reference to a managed media object
  • carries identity, not embedded binaries

MediaSet

  • canonical media container for a listing-like entity
  • supports main asset, gallery, alternates, ordering, and descriptive metadata

Conceptual shape:

MediaSet {
	primary?: MediaAssetRef
	gallery?: [MediaEntry]
	alternates?: [MediaEntry]
}

MediaEntry {
	asset: MediaAssetRef
	position: u32
	caption?: LocalizedText
	alt?: LocalizedText
	intent?: MediaIntent
}

Taxonomy Types

TaxonomySet

  • canonical classification container
  • categories, tags, segments, themes, editorial labels, collection ids

Locality Types

LocalityRef

  • reference to a place-like entity or canonical locality record

LocalityRefSet

  • ordered or typed collection of locality references
  • supports hierarchical containment and service-scope semantics

Policy Types

VisibilityPolicy

  • declared policy describing who may discover or view an entity
  • examples: private, authenticated, public, scheduled_public

LifecycleState

  • declared workflow state
  • examples: draft, review, published, archived, expired, revoked

OrderingPolicy

  • canonical ordering container
  • supports editorial weight, pinning, freshness, boost windows, and deterministic tie rules

Structural Types

Direction

  • relation orientation marker
  • examples: outbound, inbound, bidirectional

Cardinality

  • declared allowed multiplicity
  • examples: one, optional_one, many, bounded_many

CorrespondenceStrength

  • describes how strong or substitutable a mapping is
  • examples: equivalent, variant, supersession, fulfillment, partial

ValueMap

  • schema-bound metadata bag
  • only allowed where the contract explicitly declares metadata structure
  • never an escape hatch for undeclared semantics

Payload Types

FacetPayloadSet

  • collection of declared facet payloads bound to a specific kind
  • each facet payload must validate against its declared facet contract

Provenance

  • source-of-truth and import lineage data
  • supports ingestion, synchronization, and audit use cases without leaking operational details into the semantic core

Illustrative Kind Definitions

The following examples are not final schemas.

They exist to show how atlas kinds should be expressed semantically.

Hotel

hotel is a publishable hospitality entity.

It uses shared atlas semantics plus hospitality-specific facets.

Conceptual definition:

kind hotel {
	core:
		title
		summary
		media
		taxonomy
		locality
		visibility
		lifecycle
		ordering

	facets:
		hospitality
		amenities
		pricing
		availability
		contact
		geo
		seo

	relations:
		located_in -> area | city | region
		belongs_to -> brand?
		has_variant -> room_type*
		related_to -> restaurant* | beach* | excursion*

	projections:
		list_card
		detail_page
		map_card

	filters:
		locality
		amenities
		price_band
		rating
}

Room Type

room_type is a publishable variant entity.

It is not just a field on a hotel. It has independent semantics but depends on a parent hotel relation.

Conceptual definition:

kind room_type {
	core:
		title
		summary
		media
		visibility
		lifecycle
		ordering

	facets:
		hospitality
		amenities
		pricing
		availability

	relations:
		variant_of -> hotel exactly_one
		located_in -> area? | city?

	correspondences:
		same_concept_as?
		public_variant_of?
		commercial_variant_of?

	projections:
		list_card
		booking_panel
		comparison_row
}

Author

author is a publishable profile entity.

Conceptual definition:

kind author {
	core:
		title
		summary
		media
		taxonomy
		visibility
		lifecycle
		ordering

	facets:
		profile
		editorial
		contact
		seo

	relations:
		related_to -> book*
		located_in -> place?

	projections:
		list_card
		profile_page
}

Book

book is a publishable work or edition-like entity depending on the declared domain contract.

Conceptual definition:

kind book {
	core:
		title
		summary
		media
		taxonomy
		visibility
		lifecycle
		ordering

	facets:
		editorial
		commerce
		inventory
		seo

	relations:
		written_by -> author one_or_more role_bearing
		contributed_by -> author*
		belongs_to -> publisher?

	memberships:
		part_of -> series*

	correspondences:
		edition_of?
		supersedes?
		fulfills?
		public_variant_of?
		commercial_variant_of?

	projections:
		list_card
		detail_page
		purchase_card
}

Series

series is a canonical entity with ordered composition semantics.

It proves that atlas must support membership separately from ordinary relations.

Conceptual definition:

kind series {
	core:
		title
		summary
		media
		taxonomy
		visibility
		lifecycle
		ordering

	facets:
		editorial
		seo

	memberships:
		contains -> book* ordered

	relations:
		related_to -> author* | publisher*

	projections:
		list_card
		series_page
}

CUE And Rust Responsibilities

The split between CUE and Rust should be deliberate.

CUE owns contract data

CUE definitions should declare:

  • kinds
  • facets
  • relation vocabularies
  • membership vocabularies
  • correspondence vocabularies
  • field requirements
  • normalization rules expressible as contract data
  • lifecycle and visibility policies
  • projection shapes
  • query and sort surfaces

Rust owns execution

Rust should own:

  • loading and validating CUE packages
  • canonical normalization and compilation
  • deterministic storage projection
  • runtime validation of entity instances
  • relation, membership, and correspondence enforcement
  • query planning
  • projection materialization
  • event emission and operational workflows

The rule is simple:

contract semantics live in CUE, execution semantics live in Rust.

Neither side should guess what the other meant.

Invariants

k2atlas only has value if its behavior is deterministic, canonical, and mechanically derived from explicit contract data.

The following invariants are mandatory.

Contract Invariants

  • every kind must be declared explicitly
  • every facet used by a kind must be declared explicitly
  • every relation, membership, and correspondence type must be declared explicitly
  • every top-level semantic field in canonical storage must be declared explicitly
  • undeclared fields are invalid unless the contract explicitly defines an extension surface

The system must not infer semantics from payload shape alone.

Identity Invariants

  • canonical entity identity is never inferred from title, slug, or field similarity
  • semantic correspondence never replaces canonical identity
  • equality, variant, edition, fulfillment, and supersession are distinct mapping types
  • identity mappings must be directional unless the contract explicitly declares symmetry
  • multiple identity layers may coexist, but they must be named and typed explicitly

The system must not collapse "related" into "same".

Ordering Invariants

  • list ordering must be derived from explicit ordering policy or explicit membership position
  • tie-breaking rules must be deterministic and contract-defined
  • insertion order is never a valid semantic ordering rule
  • gallery order, membership order, and projection order are distinct and must not be conflated

The system must never rely on accidental storage order.

Projection Invariants

  • list-card, detail-page, and other projections must be derived from declared projection contracts
  • projection fields must be traceable back to canonical fields or declared derived rules
  • projections may omit fields but must not invent undeclared semantic fields
  • render surfaces must consume atlas projections, not reinterpret raw storage ad hoc

This keeps projection behavior canonical across products.

Relation Invariants

  • relations must validate source kind, target kind, relation type, and cardinality
  • memberships must validate ordering and composition constraints
  • role-bearing relations must validate role semantics and edge metadata
  • correspondences must validate mapping semantics independently from ordinary relations

No edge is valid merely because two ids exist.

Normalization Invariants

  • normalization rules must be declared, deterministic, and repeatable
  • normalization must not depend on UI copy, locale guesswork, or heuristic intent detection
  • repeated normalization of the same valid input must produce the same canonical representation
  • canonical storage values must be derived mechanically from explicit contract rules only

This is the determinism gate.

Query Invariants

  • filterable fields must be declared explicitly by kind or projection contract
  • sortable fields must be declared explicitly by kind or projection contract
  • query behavior must not depend on undeclared incidental storage fields
  • collection and library views must be defined by explicit contracts, not arbitrary frontend composition

This keeps query surfaces stable and portable.

Lifecycle Invariants

  • every lifecycle state must be declared explicitly
  • transitions between lifecycle states must be declared explicitly
  • visibility rules must compose with lifecycle rules deterministically
  • publishing, archival, expiry, and revocation must be modeled as semantics, not frontend conventions

This prevents state machines from leaking into ad hoc application logic.

Derivation Invariants

  • storage projection must derive from contract data
  • search projection must derive from contract data
  • API shapes must derive from contract data
  • admin/editor forms must derive from contract data
  • relation and correspondence views must derive from contract data

If the same semantic rule has to be hand-maintained in multiple implementation layers, atlas has failed its purpose.

Acceptance Gate

Any atlas feature or extension must satisfy all of the following:

  • deterministic: the same contract and input produce the same canonical result
  • canonical: one semantic rule has one declared source of truth
  • mechanical: outputs are derived from explicit contract data, not heuristic application code

If a proposed feature breaks any of these, it should be rejected or redesigned.

Runtime Architecture

k2atlas should be implemented as a contract compiler plus runtime.

The compiler loads CUE definitions and produces canonical internal representations.

The runtime uses those compiled contracts to validate entities, enforce relations, derive projections, and execute queries.

Runtime-Loaded Definitions

k2atlas should support runtime-loaded domain definitions.

This means new or updated CUE definitions can be introduced without producing a new application binary.

The application binary contains the atlas engine.

The domain model lives in versioned CUE definitions and is loaded dynamically at runtime.

This is a core design property, not a convenience feature.

Required Behavior

  • new definitions must be loadable without rebuilding the service binary
  • new definitions must be activatable without redeploying the service binary
  • activated definitions must behave as immutable runtime snapshots
  • requests must execute against a single resolved snapshot, never a mixture of live mutable definitions

What "runtime-loaded" does and does not mean

Runtime-loaded means:

  • no new binary is required to roll out a new atlas kind, facet, relation, or projection contract
  • definitions can be stored, validated, compiled, and activated by the running system

Runtime-loaded does not mean:

  • raw CUE text is interpreted ad hoc on every request
  • mutable definitions can drift during request execution
  • canonicalization can be skipped
  • validation and activation can be bypassed

The system still requires a compile-like activation step.

That step happens inside the running system and produces canonical runtime structures rather than a new executable artifact.

Source And Snapshot Model

The correct model is:

  • source contracts stored as immutable versioned CUE packages
  • compiled runtime snapshots produced from those packages
  • requests executed only against activated snapshots

This separates ontology evolution from binary deployment.

Activation Pipeline

Runtime-loaded definitions should follow this activation pipeline:

  1. store a new immutable CUE package version
  2. load and validate the package
  3. compile it into canonical internal atlas structures
  4. validate cross-kind invariants and runtime readiness
  5. activate it atomically as a new snapshot
  6. materialize or rebuild any changed projections, views, or indexes
  7. route subsequent operations against the new snapshot

Versioning Rules

  • every stored definition set must have an immutable version identifier
  • a request must bind to exactly one activated definition version
  • the system must be able to reject invalid versions without affecting the current active snapshot
  • rollback to a previous valid snapshot must be possible without binary rollback

Operational Consequences

If a new definition changes query surfaces, projections, or relation semantics, atlas may need to trigger:

  • projection rebuilds
  • collection/view rematerialization
  • index creation or migration in k2db
  • compatibility validation for existing entities

These are activation-time or background-materialization concerns, not reasons to tie atlas evolution to binary releases.

Definition Registry

Runtime-loaded definitions need a first-class registry model.

k2atlas should not treat definitions as anonymous text blobs.

Each stored definition set should have explicit registry metadata.

Definition Package

A definition package is the immutable source unit stored in the system.

Conceptual shape:

DefinitionPackage {
	package_id: PackageId
	version_id: VersionId
	created_at: Timestamp
	created_by: PrincipalId
	source_format: "cue"
	source_digest: Digest
	source_bundle: CuePackage
	status: DefinitionStatus
	notes?: string
}

Definition Status

Suggested lifecycle states for stored definitions:

  • draft
  • validated
  • compiled
  • active
  • superseded
  • rejected
  • retired

Only validated and compiled packages may become active.

Registry Responsibilities

The registry must support:

  • immutable storage of source packages
  • deterministic version addressing
  • auditability of who created and activated which version
  • lookup of current active snapshot
  • lookup of historical active snapshots
  • rollback to a previous compiled version

Snapshot Lifecycle

An activated atlas snapshot should be modeled explicitly.

Conceptual shape:

ActiveSnapshot {
	snapshot_id: SnapshotId
	package_id: PackageId
	version_id: VersionId
	activated_at: Timestamp
	activated_by: PrincipalId
	compiled_digest: Digest
	runtime_state: SnapshotRuntimeState
}

Suggested runtime states:

  • warming
  • active
  • draining
  • inactive
  • failed

This allows atomic cutover without mixed-version request handling.

Snapshot Rules

  • exactly one snapshot is active per atlas domain scope unless multi-scope activation is declared explicitly
  • a request binds to one snapshot at request start
  • a snapshot may only become active after successful validation and compilation
  • a failed activation must leave the prior snapshot intact

Compatibility And Migration

Runtime-loaded contracts require explicit compatibility rules.

Without them, atlas definitions will evolve faster than entity state and projections can safely follow.

Compatibility Classes

Every new definition version should be classified as one of:

  • compatible
  • compatible_with_rebuild
  • migration_required
  • breaking

Meaning

compatible

  • existing canonical entities remain valid
  • no rebuild beyond normal activation is required

compatible_with_rebuild

  • canonical entities remain valid
  • projections, views, or indexes must be rebuilt

migration_required

  • some canonical entities require deterministic migration before or during activation

breaking

  • activation is rejected unless an explicit migration plan is supplied

Compatibility Checks

At minimum, atlas should evaluate compatibility across:

  • required field changes
  • facet additions and removals
  • relation cardinality changes
  • target-kind changes
  • lifecycle and visibility policy changes
  • projection field changes
  • filter and sort surface changes
  • correspondence semantics changes

Migration Rules

If migration is required:

  • migration intent must be declared explicitly
  • migration must be deterministic and repeatable
  • migration must be traceable to the definition version transition
  • migration may not rely on heuristic repair of invalid historical data

If deterministic migration is not possible, activation should be rejected.

Definition Diff Model

Compatibility decisions must be based on a canonical structural diff, not on raw text comparison.

Atlas should compare compiled definition snapshots, not source formatting.

Diff Scope

At minimum, a diff must detect changes in:

  • kind declarations
  • core field requirements
  • facet requirements
  • relation vocabularies
  • membership vocabularies
  • correspondence vocabularies
  • target-kind constraints
  • cardinality constraints
  • lifecycle states and transitions
  • visibility policies
  • projection shapes
  • filter surfaces
  • sort surfaces
  • normalization rules

Diff Classes

Each detected change should be classified.

Suggested classes:

  • additive
  • restrictive
  • semantic
  • projection_only
  • operational
  • breaking

Meaning

additive

  • new optional facet
  • new optional projection field
  • new optional relation type
  • new filter or sort surface that does not invalidate existing entities

restrictive

  • required field added
  • cardinality tightened
  • allowed target kinds narrowed
  • visibility or lifecycle rules narrowed

semantic

  • relation meaning changed
  • correspondence type meaning changed
  • normalization rules changed
  • kind interpretation changed without obvious shape breakage

projection_only

  • list-card or detail projection changed
  • search or collection materialization changed
  • no canonical entity meaning changed

operational

  • index requirements changed
  • materialization strategy changed
  • rebuild policy changed

breaking

  • previously valid canonical entities become invalid without deterministic migration
  • previous query contracts become ambiguous or undefined
  • identity or correspondence semantics become lossy or contradictory

Compatibility Decision Rules

The system should derive compatibility from the diff classes, not from a manually asserted label alone.

Recommended rules:

  • only additive changes may be auto-activated with no rebuild
  • projection_only and operational changes require rebuild planning before activation
  • restrictive changes require entity validation against existing canonical state
  • semantic changes require explicit review and may require migration or dual-read compatibility
  • breaking changes must be rejected until a deterministic migration plan exists

Diff Output

The compatibility engine should emit a machine-readable report analogous to:

DefinitionDiff {
	from_version: VersionId
	to_version: VersionId
	changes: [DiffChange]
	compatibility_class: CompatibilityClass
	requires_rebuild: bool
	requires_migration: bool
	blockers: [CompatibilityBlocker]
}

This report should drive activation decisions and materialization planning.

Entity Read And Write Lifecycle

Atlas entity operations must bind explicitly to an active snapshot.

The system must never allow raw payloads to bypass snapshot-bound validation and normalization.

Write Lifecycle

Every create or update operation should follow this sequence.

  1. bind request to active snapshot S
  2. authorize the operation via k2rbac
  3. resolve the target kind under snapshot S
  4. validate raw payload against the compiled kind contract
  5. normalize payload deterministically
  6. validate relations, memberships, and correspondences against snapshot S
  7. persist the canonical entity and edge records with snapshot provenance
  8. emit materialization and lifecycle events
  9. update or enqueue derived projections and views
  10. return a response derived from snapshot S

Write Rules

  • a write must never validate against one snapshot and project against another
  • canonical writes must record which snapshot normalized them
  • relation and correspondence enforcement must happen before canonical commit
  • failed projection rebuilds must not silently roll back canonical truth unless the operation is explicitly transactional across both layers

Read Lifecycle

Every read operation should follow this sequence.

  1. bind request to active snapshot S or an explicitly requested compatible snapshot
  2. authorize visibility and action semantics via k2rbac
  3. resolve the requested projection contract under snapshot S
  4. read canonical entity or materialized view data consistent with snapshot S
  5. apply declared query/filter/sort rules under snapshot S
  6. return a projection traceable to canonical fields and snapshot S

Read Rules

  • a read must never merge projections from multiple active snapshots implicitly
  • query behavior must be evaluated under the snapshot that declares the query surface
  • library and collection views must declare which snapshot produced them
  • stale materializations must be rejected, rebuilt, or served only under explicit degraded-mode rules

Entity Provenance

Atlas should preserve provenance on canonical writes and derived outputs.

At minimum, an entity record should carry:

  • canonical entity id
  • kind id
  • normalized snapshot version
  • created at
  • created by
  • last updated at
  • last updated by
  • optional source lineage

This is necessary for migration, audit, and reproducibility.

Revalidation And Reprojection

When a new snapshot becomes active, existing entities may need one or more follow-up actions:

  • no action
  • reprojection only
  • relation revalidation
  • correspondence revalidation
  • full entity revalidation
  • deterministic migration

These actions should be derived from the compatibility report, not decided ad hoc in application code.

Materialization Model

Atlas activation may change not only validation semantics but also read surfaces.

For that reason, projections and views should be treated as materialized derivatives of canonical entities plus the active snapshot.

Materialized Outputs

At minimum, atlas may maintain:

  • canonical entity records
  • relation edge records
  • membership edge records
  • correspondence maps
  • list-card projections
  • detail projections
  • collection or library views
  • search/index projections

Materialization Rules

  • every materialized output must record which snapshot produced it
  • rebuild jobs must be restartable and idempotent
  • partial rebuilds must not silently become the new truth
  • read paths must either bind to a consistent snapshot or reject stale mixed materialization

Operational APIs

The first atlas management surface should expose explicit operations for definition and snapshot control.

Suggested operations:

  • create_definition_package
  • validate_definition_package
  • compile_definition_package
  • activate_definition_package
  • rollback_snapshot
  • diff_definition_versions
  • check_compatibility
  • plan_rebuild
  • run_materialization
  • inspect_active_snapshot

These operations should be first-class atlas semantics, not hidden implementation details.

Pipeline

The first implementation should follow this pipeline.

  1. Load CUE packages.
  2. Validate package structure and vocabulary declarations.
  3. Compile kinds, facets, relations, memberships, and correspondences into canonical Rust structures.
  4. Validate cross-references and invariants.
  5. Produce compiled atlas definitions.
  6. Use compiled definitions at runtime for normalization, validation, projection derivation, and query planning.

Rust Subsystems

The Rust side should be split into small deterministic subsystems.

loader

  • loads atlas CUE packages
  • resolves package roots and imports
  • returns raw contract documents

compiler

  • compiles raw contract documents into canonical Rust definitions
  • resolves identifiers, references, and declared vocabularies
  • rejects ambiguous or undeclared semantics

validator

  • validates entity payloads against compiled kind contracts
  • validates relations, memberships, and correspondences
  • enforces cardinality, target-kind, and lifecycle rules

normalizer

  • applies deterministic normalization rules
  • emits canonical entity representation only
  • never performs heuristic inference

projector

  • derives storage, search, list-card, and detail projections
  • guarantees traceability back to declared contracts

planner

  • compiles query/filter/sort requests against declared query surfaces
  • rejects undeclared query behavior

runtime

  • orchestrates entity create/update/publish/archive operations
  • enforces lifecycle, visibility, and relation constraints
  • interacts with k2db, k2rbac, and k2mx

materializer

  • maintains derived views and collection projections
  • updates relation and correspondence maps
  • keeps read surfaces consistent with canonical state

Canonical Rust Types

The first compiler target should be a set of canonical internal types analogous to:

CompiledAtlas {
	kinds: Map<KindId, CompiledKind>
	facets: Map<FacetId, CompiledFacet>
	relation_types: Map<RelationType, CompiledRelationType>
	membership_types: Map<MembershipType, CompiledMembershipType>
	correspondence_types: Map<CorrespondenceType, CompiledCorrespondenceType>
	projections: Map<ProjectionId, CompiledProjection>
}

Each compiled type must be free of ambiguity.

By the time runtime execution starts, all references should already be resolved.

Persistence Boundary

k2atlas should not own low-level storage primitives.

It should produce canonical records and derived projections for k2db to persist.

The persistence split should be:

  • atlas owns semantic compilation, normalization, and projection derivation
  • k2db owns persistence mechanics, indexing, and retrieval execution

Integration Boundary

k2atlas should integrate with the other k2 components as follows.

k2login

  • identifies acting principals

k2rbac

  • authorizes create, update, publish, archive, relate, and view operations

k2mx

  • emits lifecycle and projection events
  • receives import or sync triggers where applicable

k2db

  • stores canonical entities, edges, correspondence maps, and derived read models

First CUE Sketches

These are illustrative sketches only.

They show the shape atlas definitions should have, not finalized syntax.

Core Types Sketch

package atlas

#EntityId: string
#KindId: string
#RelationType: string
#MembershipType: string
#CorrespondenceType: string

#LifecycleState: "draft" | "review" | "published" | "archived" | "expired" | "revoked"
#VisibilityPolicy: "private" | "authenticated" | "public" | "scheduled_public"

#LocalizedText: {
	default_locale: string
	values: [string]: string
}

#OrderingPolicy: {
	weight?: int
	pinned?: bool
	freshness_window?: string
	tie_breaker: "id" | "created_at" | "updated_at" | "title"
}

#AtlasEntity: {
	id: #EntityId
	kind: #KindId
	title: #LocalizedText
	summary?: #LocalizedText
	visibility: #VisibilityPolicy
	lifecycle: #LifecycleState
	ordering?: #OrderingPolicy
	facets: [string]: _
}

Hotel Kind Sketch

package atlas

#Kinds: hotel: {
	core: {
		title: required: true
		summary: required: true
		media: required: false
		taxonomy: required: false
		locality: required: true
		visibility: required: true
		lifecycle: required: true
		ordering: required: false
	}

	facets: {
		hospitality: required: true
		amenities: required: false
		pricing: required: false
		availability: required: false
		contact: required: false
		geo: required: false
		seo: required: false
	}

	relations: {
		located_in: {
			targets: ["area", "city", "region"]
			cardinality: "one_or_more"
		}
		has_variant: {
			targets: ["room_type"]
			cardinality: "many"
		}
	}

	projections: {
		list_card: true
		detail_page: true
		map_card: true
	}

	filters: {
		locality: true
		amenities: true
		price_band: true
		rating: true
	}
}

Book And Series Sketch

package atlas

#Kinds: book: {
	facets: {
		editorial: required: true
		commerce: required: false
		inventory: required: false
		seo: required: false
	}

	relations: {
		written_by: {
			targets: ["author"]
			cardinality: "one_or_more"
			role_bearing: true
			roles: ["lead_author", "co_author", "translator", "editor", "illustrator"]
		}
	}

	correspondences: {
		edition_of: true
		supersedes: true
		fulfills: true
		public_variant_of: true
		commercial_variant_of: true
	}
}

#Kinds: series: {
	memberships: {
		contains: {
			targets: ["book"]
			ordered: true
			cardinality: "many"
		}
	}

	projections: {
		list_card: true
		series_page: true
	}
}

First Implementation Slice

The safest first slice is small but complete.

It should implement:

  1. contract loading from CUE
  2. compilation into canonical Rust definitions
  3. one entity create/update normalization path
  4. relation validation
  5. ordered membership validation
  6. one list-card projection path
  7. one detail projection path
  8. deterministic query/filter/sort validation

Recommended initial kinds:

  • hotel
  • room_type
  • author
  • book
  • series

This set is enough to stress locality, variants, ordered composition, role-bearing edges, and typed correspondence without making the first implementation unbounded.

Relations

Relations must be first-class, typed, directional, and contract-defined.

Loose foreign keys are insufficient because they do not carry semantic meaning or constraints.

Initial Relation Vocabulary

  • located_in
  • contains
  • belongs_to
  • variant_of
  • has_variant
  • near
  • serves
  • related_to
  • recommended_with
  • part_of
  • references

Examples

  • hotel located_in area
  • area located_in city
  • room type variant_of hotel
  • hotel has_variant room type
  • restaurant near beach
  • excursion recommended_with hotel
  • Phuket activity page contains listings
  • beach club belongs_to hospitality group

Relation Requirements

Each relation definition must declare:

  • type
  • target_kind
  • target_id
  • cardinality
  • inverse
  • constraints
  • optional edge metadata

This allows definitions such as:

  • a room_type must have exactly one variant_of edge to a hotel
  • a hotel may have many has_variant edges to room_type
  • a restaurant may have one or more located_in edges to area-level localities

Ordered Composition

Some entities do not merely relate to other entities. They compose exact members in an exact order.

Examples:

  • a book series contains exact books in an exact sequence
  • a curated guide contains exact listings in editorial order
  • a hotel may surface exact room types in a preferred order

Plain membership is insufficient for these cases.

k2atlas must support ordered composition edges with explicit sequence semantics.

An ordered membership edge should be able to carry:

  • target_id
  • target_kind
  • position
  • label
  • required
  • constraints
  • optional inclusion metadata

This allows a series entity to mean more than "related books".

It means an ordered composition of exact members.

Role-Bearing Relations

Some relations do not just connect entities. They express the role one entity plays with respect to another.

Examples:

  • a book is written_by an author
  • a book is contributed_by an illustrator
  • a book is translated_by a translator
  • a work is edited_by an editor

The edge itself carries semantic meaning and may require metadata.

A role-bearing relation should support:

  • type
  • role
  • target_id
  • target_kind
  • billing_order
  • weight
  • primary
  • optional contribution metadata

This is necessary for publishing, commerce, hospitality, and other domains where the relationship itself has structure.

Projections And Views

Not every surfaced thing should be treated as a canonical entity of the same class.

k2atlas must distinguish between:

  • canonical entities
  • curated collections
  • derived views
  • render projections

Examples:

  • an author profile is a canonical entity
  • a book is a canonical entity
  • a series may be a canonical entity with ordered membership
  • a library may be a scoped or curated view over entities rather than a single canonical entity

This distinction matters because views and projections often derive from canonical entities but do not own the same semantics or lifecycle.

Identity And Correspondence

k2atlas must support more than one notion of sameness.

Two records may refer to the same conceptual thing while remaining operationally distinct.

Examples:

  • a purchased item may refer to edition 1 of a book
  • a public catalog listing may refer to edition 2 of that same conceptual work
  • both may need to be treated as related without being equal

This means atlas cannot rely on naive equality.

It must support typed, directional correspondence between entities.

Identity Layers

At minimum, the system should distinguish:

  • canonical entity identity
  • semantic identity
  • commercial identity
  • public presentation identity

Correspondence Vocabulary

Initial correspondence and mapping types may include:

  • same_concept_as
  • edition_of
  • supersedes
  • public_variant_of
  • commercial_variant_of
  • fulfills
  • entitles_access_to

These are not all symmetric.

Some are directional, some may be many-to-one, and some may represent partial equivalence rather than identity.

For example:

  • purchased listing A may fulfills public listing A'
  • public listing A' may public_variant_of conceptual work W
  • commercial listing A may commercial_variant_of conceptual work W
  • edition 2 may supersedes edition 1

The system must preserve these distinctions explicitly instead of collapsing them into a single equality relation.

Facets

Facets carry domain variation while the core remains stable.

Facets are not free-form bags of optional fields.

They are explicit contract modules with deterministic structure, validation, and semantics.

Example Facets

  • hospitality
  • commerce
  • profile
  • mobility
  • amenities
  • pricing
  • availability
  • contact
  • seo
  • editorial
  • geo
  • inventory

Example Compositions

A hotel might compose:

  • hospitality
  • amenities
  • pricing
  • availability
  • contact
  • geo
  • seo

A dating_profile might compose:

  • profile
  • media
  • preferences
  • contact
  • visibility

A car_rental might compose:

  • commerce
  • pricing
  • availability
  • mobility
  • contact
  • geo

Derived Outputs

The contract is not just for input validation.

From a kind definition, k2atlas should mechanically derive:

  • canonical entity schema
  • accepted facet set
  • validation rules
  • normalization rules
  • lifecycle rules
  • visibility rules
  • allowed relations
  • queryable and filterable fields
  • sortable fields
  • storage projection
  • search projection
  • list-card projection
  • detail-page projection
  • admin and editor form projection
  • indexing requirements
  • API contract

From relation and correspondence definitions, k2atlas should also derive:

  • ordered membership projections
  • contributor role projections
  • identity and variant maps
  • collection and library views
  • edition and fulfillment navigation

If these outputs still have to be hand-authored repeatedly in multiple places, the system has failed its purpose.

Definition Model

A kind definition is not merely a list of fields.

It is a semantic contract that states:

  • this entity is of kind X
  • it uses these facets
  • it requires these fields
  • it permits these relations
  • it exposes these filters
  • it derives these projections
  • it participates in these workflows

The contract describes the semantic behavior of an entity kind, not just its payload.

Hard Boundaries

To keep k2atlas deterministic, canonical, and mechanically derivable:

  • no heuristic inference from labels or UI copy
  • no undeclared fields in canonical storage
  • no relation without explicit type and target constraints
  • no correspondence without explicit mapping semantics
  • no facet without a declared schema
  • no frontend-specific semantics in the core contract
  • no page-builder concerns inside entity definitions
  • no schema behavior that depends on application code guessing intent

v0 Scope

k2atlas v0 should support:

  • one canonical AtlasEntity
  • typed kind definitions loaded from CUE
  • typed facet composition
  • typed directional relations
  • ordered membership relations
  • role-bearing contributor relations
  • typed identity correspondence
  • lifecycle and visibility policies
  • derived list and detail projections
  • deterministic query, filter, and sort surfaces

That is enough to prove the architecture without trying to solve every downstream problem in the first iteration.

Working Summary

k2atlas is the missing semantic layer between raw storage and rendered pages.

It solves the repeated complexity of discoverable entities once, generically, so frontends can consume already-typed, already-related, already-curated data instead of rebuilding semantics ad hoc.