ID Scheme
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-jpais renamed toadapter: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 prefix | Used for | Example |
|---|---|---|
adapter: | Component Library entries | adapter:java/spring-data-jpa@3.2.4 |
module: | Module Library entries | module:auth/jwt-with-rbac@1.0.0 |
archetype: | Archetype definitions | archetype:rag-chatbot@0.1.0 |
capability: | Capability registry entries | capability:persistence/transactions/v1 |
contract: | Contract registry entries | contract:persistence/repository/v1 |
scaffolder: | External scaffolder integrations | scaffolder:jhipster@8.6.0 |
slot: | Slots within an archetype | slot:rag-chatbot/llm-provider |
seam: | Seams within an archetype | seam: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_namefields 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-446655440000Assigned 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:
- The Manifest’s
idfield is updated to the new slug. - The Manifest’s
lifecycle.previous_slugsarray records the old slug with the date of change. - The UUID does not change.
- 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.
- An ADR is filed recording the reason for the rename.
This is a deliberately heavy process. Renames are not routine.
Versioning Within Identifiers
| Entity | Version style | Example |
|---|---|---|
| Adapter | semver | adapter:java/spring-data-jpa@3.2.4 |
| Module | semver | module:auth/jwt-with-rbac@1.0.0 |
| Archetype | semver | archetype:rag-chatbot@0.1.0 |
| Scaffolder | semver | scaffolder:jhipster@8.6.0 |
| Capability | integer | capability:persistence/transactions/v1 |
| Contract | integer | contract:persistence/repository/v1 |
| Manifest schema | integer | manifest-v1 |
| Archetype Spec schema | integer | archetype-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.
Related
- Naming Conventions — what we call things
- Concepts → Manifest — where IDs live
- Schemas → Adapter Manifest v1 — the formal schema for the identity block