Skip to content

ID Scheme

Accepted

Almathal uses a two-identifier model for every registry entity: a human-readable namespaced slug for day-to-day reference, and an immutable UUID for audit and historical resolution.

Why Two Identifiers

A single identifier cannot serve both roles:

  • Slugs alone are mutable. If adapter:java/spring-data-jpa is renamed to adapter:java/spring-data-relational (because upstream renamed it), every audit record referencing the old slug breaks.
  • UUIDs alone are unreadable. Manifests, ADRs, and documentation referencing components by UUID are impossible to read or write by hand.

The solution: humans and most tooling reference the slug. Audit logs, build records, and database joins reference the UUID. The Manifest carries both.

Namespaced Slug Format

<type>:<namespace>/<name>[@<version>]
Type prefixUsed forExample
adapter:Component Library entriesadapter:java/spring-data-jpa@3.2.4
module:Module Library entriesmodule:auth/jwt-with-rbac@1.0.0
archetype:Archetype definitionsarchetype:rag-chatbot@0.1.0
capability:Capability registry entriescapability:persistence/transactions/v1
contract:Contract registry entriescontract:persistence/repository/v1
scaffolder:External scaffolder integrationsscaffolder:jhipster@8.6.0
slot:Slots within an archetypeslot:rag-chatbot/llm-provider
seam:Seams within an archetypeseam:rag-chatbot/document-ingestion

The @version suffix is optional in most references; it locks the entity to a specific version when needed for reproducibility.

Namespace Rules

  • All lowercase
  • Segments separated by /
  • Within a segment, words separated by - (kebab-case)
  • No whitespace, no path separators other than /, no quotes
  • Maximum total length 200 characters
  • ASCII only for the slug; Unicode is allowed in display_name fields in the Manifest

Namespace Hierarchy by Type

Adapters — namespaced by language slice:

adapter:java/<adapter-name>
adapter:typescript/<adapter-name>
adapter:python/<adapter-name>
adapter:ai/<adapter-name>
adapter:infra/<adapter-name>

Modules — namespaced by domain:

module:auth/<module-name>
module:payments/<module-name>
module:billing/<module-name>
module:observability/<module-name>

Archetypes — flat namespace (no subdivision):

archetype:<archetype-name>

Capabilities and Contracts — namespaced by category with mandatory version suffix:

capability:<category>/<capability-name>/v<N>
contract:<category>/<contract-name>/v<N>

UUID Format

Standard UUIDv4 (random). Example:

550e8400-e29b-41d4-a716-446655440000

Assigned at admission to the registry. Never changes for the lifetime of the entity. Stored in the entity’s Manifest in the identity.uuid field.

When an entity is deprecated and replaced, the replacement receives a new UUID; the original UUID is retained on the deprecated entity. The Manifest’s lifecycle.successor_adapter (or successor_module, etc.) references the successor by UUID, allowing the lineage to be traced even when slugs change.

Use in Manifests

Every Manifest carries both identifiers at the top:

{
"identity": {
"id": "adapter:java/spring-data-jpa",
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"version": "3.2.4",
"display_name": "Spring Data JPA"
}
}

The id is the slug. The uuid is the immutable anchor.

Use in Specs

Archetype Specs reference Adapters and Modules by slug only:

{
"adapter_slots": [
{
"slot_id": "slot:rag-chatbot/persistence",
"selected": "adapter:java/spring-data-jpa@3.2.4"
}
]
}

The slug includes the version, locking the Spec to a specific release. When a generation runs, the platform records both slug and the UUID resolved at that moment in the build record, so historical builds remain resolvable even if the slug is later renamed.

Use in Audit Logs and Build Records

Audit logs and build records reference UUIDs:

{
"build_id": "build-7a3f8c2e",
"timestamp": "2026-06-10T14:33:12Z",
"archetype_uuid": "...",
"adapters_used": [
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"slug_at_build_time": "adapter:java/spring-data-jpa@3.2.4"
}
]
}

Storing both the UUID and the slug at build time gives a self-contained record: the UUID is the durable anchor, the slug is the readable label as it existed when the build ran.

Renaming Slugs

Slugs can be renamed. Renaming follows this process:

  1. The Manifest’s id field is updated to the new slug.
  2. The Manifest’s lifecycle.previous_slugs array records the old slug with the date of change.
  3. The UUID does not change.
  4. The platform maintains a slug-alias resolver that maps old slugs to current ones for one minor version after rename. After that, old slugs return a deprecation error.
  5. An ADR is filed recording the reason for the rename.

This is a deliberately heavy process. Renames are not routine.

Versioning Within Identifiers

EntityVersion styleExample
Adaptersemveradapter:java/spring-data-jpa@3.2.4
Modulesemvermodule:auth/jwt-with-rbac@1.0.0
Archetypesemverarchetype:rag-chatbot@0.1.0
Scaffoldersemverscaffolder:jhipster@8.6.0
Capabilityintegercapability:persistence/transactions/v1
Contractintegercontract:persistence/repository/v1
Manifest schemaintegermanifest-v1
Archetype Spec schemaintegerarchetype-spec-v1

Capabilities and Contracts use integer versions because they are interfaces. They evolve only in major versions; there is no concept of a minor or patch change to an interface.

Adapters and Modules use semver because they are implementations. They can have patch updates, minor additions, and major breaking changes.