UCCA World Container Specification v1.0¶
Classification: INTERNAL — Architecture
Owner: Tim
Status: Draft
Date: 2026-03-04
1. Purpose¶
This document defines the canonical structure for a UCCA World Container — the standard deployable unit that encapsulates a regulatory domain. Every world, regardless of jurisdiction or industry, conforms to this specification. The specification serves as the "mother horda" — the authoritative template from which all world instances are derived.
No world is built from scratch. Every world is an instantiation of this template with domain-specific variables.
2. Platform Layer Model¶
UCCA operates a four-layer access hierarchy. The World Container exists at Layer 2 and provides the structural foundation for Layers 3 and 4.
Layer 1 — UCCA Platform (Super Admin)¶
Operators: UCCA staff (Tim, Jimmy, future team).
Scope: Full platform visibility. All clients, all worlds, governance, health, billing, account switcher.
URL pattern: ops.ucca.online/...
Database: ops-db (platform telemetry, client registry, billing).
Layer 2 — Client Administration (UCCA-side)¶
Operators: UCCA staff, scoped to a single client.
Scope: Internal CRM/admin for one customer — billing, support notes, data analytics, world configuration, ingestion monitoring. The client never sees this layer.
URL pattern: ops.ucca.online/clients/[client-id]/...
Database: ops-db (client record) + client's world database(s) (read access).
Layer 3 — Client Environment¶
Operators: Client admin (Bill) and client staff.
Scope: The client's own control panel. Bill manages his business here — onboards staff, assigns roles, configures security profiles, manages compliance, views his data. Staff see the same environment scoped by role permissions. Bill can white-label this layer.
URL pattern: [client-slug].ucca.online/... or client's own domain (white-label).
Database: Client's world database(s) via contract endpoints.
Layer 4 — Client End Users¶
Operators: Bill's customers / end users.
Scope: Flat access layer. Bill provisions users here. Primarily access control — consume data, no management. Bill can step down into this view. UCCA hides this layer by default but can enable visibility.
URL pattern: Same domain as Layer 3, session-scoped.
Database: Same as Layer 3, read-only subset.
Step-Down Mechanic¶
Each layer's admin can step into the layer below and see what those users see:
- Layer 1 → steps into Layer 2 (select client from account switcher)
- Layer 2 → steps into Layer 3 (view as client admin)
- Layer 3 → steps into Layer 4 (view as end user)
The step-down is a session context switch, not a URL change. A banner indicates the current viewing context.
3. What Is a World¶
A World is a self-contained regulatory domain. It represents one jurisdiction-industry combination with its own:
- Authority data (the regulatory register for that domain)
- Schema (conformant to the canonical UCCA schema contract)
- Ingestion pipeline (domain-specific data sourcing)
- API endpoints (conformant to the UCCA endpoint contract)
- Configuration (infrastructure bindings, metadata, auth)
Examples of worlds:
au-vet— Australian Vocational Education and Traininguk-caa— United Kingdom Civil Aviation Authorityus-faa— United States Federal Aviation Administrationau-ahpra— Australian Health Practitioner Regulation Agency
A world is not a customer. A world is a domain. Multiple customers can operate within the same world (e.g., multiple RTOs in au-vet). A customer may also span multiple worlds.
4. World Container Directory Structure¶
Every world container conforms to this directory structure. No exceptions. No additions outside this tree without specification amendment.
worlds/[world-id]/
│
├── world.config.json # World metadata and infrastructure bindings
│
├── schema/
│ └── schema.sql # Canonical database schema for this world
│
├── api/
│ ├── qualifications.js # Qualification endpoints
│ ├── units.js # Unit/competency endpoints
│ ├── authorities.js # Authority/provider endpoints (RTOs, etc.)
│ ├── scope.js # Scope of registration endpoints
│ ├── verify.js # Verification endpoints
│ └── health.js # World health check endpoint
│
├── tools/
│ ├── ingest/ # Data ingestion scripts (domain-specific)
│ │ ├── source-config.json # Source API configuration
│ │ └── [source]-parser.mjs # Parser scripts per data source
│ ├── enrich/ # Enrichment scripts
│ └── validate/ # Data validation scripts
│
├── assets/
│ ├── branding/ # World-specific branding (if applicable)
│ └── reference/ # Reference data, code tables
│
└── docs/
├── WORLD.md # World documentation
├── DATA-SOURCES.md # Authority data source documentation
└── CHANGELOG.md # World change log
5. world.config.json — The World Manifest¶
This is the single source of truth for a world's identity and infrastructure bindings. The platform reads this file to know what a world is and how to connect to it.
{
"world_id": "au-vet",
"display_name": "Australian VET",
"jurisdiction": "AU",
"domain": "Vocational Education and Training",
"status": "active",
"version": "1.0.0",
"authority_source": {
"name": "training.gov.au",
"type": "government_api",
"base_url": "https://training.gov.au/api",
"refresh_cadence": "weekly",
"mirror_strategy": "full_local"
},
"infrastructure": {
"compute": {
"provider": "cloudflare",
"type": "workers",
"binding": "world_worker"
},
"database": {
"provider": "cloudflare",
"type": "d1",
"binding": "rtopacks_db",
"override_endpoint": null
},
"storage": {
"provider": "cloudflare",
"type": "r2",
"bucket": "au-vet-assets",
"override_endpoint": null
},
"backup": {
"provider": "google",
"type": "drive",
"folder_id": "xxx",
"override_endpoint": null
}
},
"endpoints": {
"qualifications": "/api/worlds/au-vet/qualifications",
"units": "/api/worlds/au-vet/units",
"authorities": "/api/worlds/au-vet/authorities",
"scope": "/api/worlds/au-vet/scope",
"verify": "/api/worlds/au-vet/verify",
"health": "/api/worlds/au-vet/health"
},
"schema_version": "v4",
"owner": {
"client_id": "ucca-internal",
"contact": "tim@ucca.online"
},
"feature_flags": {
"white_label": false,
"end_user_layer": false,
"custom_infrastructure": false
}
}
Infrastructure Override Pattern¶
The override_endpoint field in each infrastructure block is the decoupling mechanism. When null, the world uses the default UCCA infrastructure (Cloudflare). When populated, the world's API routes call the override endpoint instead.
This is how Bill runs his data on AWS while using the UCCA verification engine:
"database": {
"provider": "aws",
"type": "rds-postgres",
"binding": null,
"override_endpoint": "https://api.newclient.com/data"
}
The UCCA platform doesn't care. It calls the contract endpoints. The world config routes those calls to wherever the data lives.
6. Endpoint Contract¶
Every world must expose these endpoints. The implementation varies by infrastructure choice. The contract does not.
Required Endpoints¶
| Endpoint | Method | Purpose | Response Contract |
|---|---|---|---|
| /qualifications | GET | List/search qualifications | { items: [], total, page, limit } |
| /qualifications/[code] | GET | Single qualification with units | { qualification: {}, units: { core: [], elective: [] }, specialisations: [] } |
| /units | GET | List/search units | { items: [], total, page, limit } |
| /units/[code] | GET | Single unit with reverse lookup | { unit: {}, qualifications: [] } |
| /authorities | GET | List/search authorities (RTOs, etc.) | { items: [], total, page, limit } |
| /authorities/[code] | GET | Single authority with scope | { authority: {}, scope: [] } |
| /scope | GET | Scope lookup | { items: [], total, page, limit } |
| /verify | POST | Verification request | { result: {}, evidence_chain: [] } |
| /health | GET | World health status | { status, database, last_sync, record_counts } |
Response Headers (All Endpoints)¶
All world endpoints must include UCCA provenance headers:
X-UCCA-World: au-vet
X-UCCA-Schema-Version: v4
X-UCCA-Source: training.gov.au
X-UCCA-Timestamp: 2026-03-04T10:00:00Z
Search Convention¶
All list endpoints accept: ?q=search&page=1&limit=25&sort=code&order=asc
Error Convention¶
All endpoints return errors as: { error: { code, message, world_id } }
7. Schema Contract¶
Every world's database schema must include these canonical tables. Column names are standardised. Additional domain-specific columns are permitted but must not conflict with canonical columns.
Required Tables¶
| Table | Purpose | Canonical Columns |
|---|---|---|
| qualifications | Credential register | qual_code, title, status, level, package_code, package_title |
| units | Competency register | unit_code, title, status, usage_recommendation |
| authorities | Provider register | authority_code, name, status, type |
| qualification_units | Qual-unit junction | qualification_code, unit_code, role (core/elective) |
| authority_scope | Authority-qual junction | authority_code, qual_code, status |
| qualification_specialisations | Specialisation register | qualification_code, specialisation_code, title |
Naming Convention¶
- World-specific tables are prefixed with the world ID:
auvet_rto_contacts - Canonical tables use generic names (no prefix)
- Junction tables use the pattern
[parent]_[child]
8. Terraform Module — The Mother Horda¶
The world container is provisioned via a Terraform module. The module is the authoritative definition of what a world IS. Individual worlds are instantiations with variables.
Module Structure¶
infrastructure/
modules/
world/ # The mother horda
main.tf # Resource definitions
variables.tf # What makes each world unique
outputs.tf # What a world exposes
d1.tf # Database provisioning
r2.tf # Object storage provisioning
worker.tf # Compute provisioning
dns.tf # DNS and routing
security.tf # WAF, rate limiting, headers
sandbox/
main.tf # Test instantiation of the module
terraform.tfvars # Sandbox variables
environments/
au-vet/
main.tf # module "au-vet" { source = "../../modules/world" }
terraform.tfvars # au-vet specific variables
[future-world]/
main.tf
terraform.tfvars
Module Variables (variables.tf)¶
variable "world_id" {
description = "Unique world identifier (e.g., au-vet, uk-caa)"
type = string
}
variable "display_name" {
description = "Human-readable world name"
type = string
}
variable "jurisdiction" {
description = "ISO country code"
type = string
}
variable "domain" {
description = "Regulatory domain name"
type = string
}
variable "client_id" {
description = "Owning client identifier"
type = string
default = "ucca-internal"
}
variable "database_name" {
description = "D1 database name"
type = string
}
variable "r2_bucket" {
description = "R2 bucket name for world assets"
type = string
}
variable "custom_domain" {
description = "Custom domain for white-label (null for default)"
type = string
default = null
}
variable "enable_end_user_layer" {
description = "Enable Layer 4 for this world"
type = bool
default = false
}
Module Outputs (outputs.tf)¶
output "world_id" {
value = var.world_id
}
output "database_id" {
value = cloudflare_d1_database.world_db.id
}
output "api_endpoint" {
value = "https://api.ucca.online/worlds/${var.world_id}"
}
output "health_endpoint" {
value = "https://api.ucca.online/worlds/${var.world_id}/health"
}
Sandbox Usage¶
# sandbox/main.tf
module "sandbox_world" {
source = "../modules/world"
world_id = "sandbox"
display_name = "Sandbox World"
jurisdiction = "XX"
domain = "Testing"
database_name = "sandbox-db"
r2_bucket = "sandbox-assets"
}
The sandbox is where module changes are tested. When satisfied, the module is committed and all environments inherit the change on next terraform apply.
9. Isolation Boundaries¶
Data Isolation¶
- Each world has its own D1 database instance. No shared tables across worlds.
- Each world has its own R2 bucket. No shared object storage.
- Platform data (ops-db) never contains world-specific authority data.
Code Isolation¶
- World-specific code lives under
worlds/[world-id]/. No world code in platform directories. - API routes are namespaced:
/api/worlds/[world-id]/... - Shared platform code (auth, billing, telemetry) lives in platform directories and is imported by worlds, never duplicated.
Compute Isolation¶
- Default: all worlds share the ops Worker with route-based dispatch.
- Scale: individual worlds can be promoted to their own Worker when traffic justifies it.
- Custom infrastructure: worlds with
override_endpointrun their own compute entirely.
Auth Isolation¶
- Layer 1/2 auth: UCCA platform credentials. Managed by UCCA.
- Layer 3/4 auth: Client credentials. Managed by client admin.
- Cross-layer access is via step-down tokens, not shared credentials.
10. Migration Path — RTOpacks as First Container¶
RTOpacks (au-vet) is currently interleaved with the Layer 1 platform. The migration to a proper world container requires:
Phase 1 — Namespace API Routes¶
Current: /api/ops/qualifications/
Target: /api/worlds/au-vet/qualifications/
Maintain /api/ops/ routes as redirects during transition.
Phase 2 — Relocate World Code¶
Current: apps/ops-v2/app/api/ops/qualifications/
Target: worlds/au-vet/api/qualifications.js
The ops app imports world API handlers rather than containing them.
Phase 3 — Isolate World UI¶
Current: /w/[workspace]/ops/... pages contain world-specific data views.
Target: World data views are loaded from world container, rendered within Layer 2 chrome.
Phase 4 — Generate world.config.json¶
Create the au-vet manifest from existing configuration. This becomes the reference config for all future worlds.
11. Code Classification Prism¶
Until the platform/world boundary is fully understood, every file in a world container carries a classification header. This is an observational tool, not a governance decision. The classifications evolve as patterns emerge.
Classification Header¶
Every source file in the world container includes this header block:
// @ucca-scope: platform | world | unknown
// @ucca-maintainer: ucca | client | shared | unknown
// @ucca-versioning: platform-track | world-track | independent
Scope — where this code conceptually belongs:
platform— generic to all worlds. UCCA maintains this. Qualification search logic, pagination, auth, schema migrations, health checks.world— specific to this regulatory domain. The TGA parser, AU-VET specific enrichment rules, domain-specific validation.unknown— not yet classified. This is the honest default.
Maintainer — who is responsible for this code in a multi-tenant future:
ucca— UCCA maintains and updates. Client receives updates automatically. Breaking changes follow a release cycle.client— client owns and maintains. UCCA provides the scaffold but the client customises. Ingestion scripts for their data sources, custom business logic.shared— both parties touch this. Configuration files, role templates, branding assets. Requires clear merge/override rules.unknown— not yet determined. Default classification.
Versioning — how updates propagate:
platform-track— this file tracks the platform release. When UCCA updates the module, this file updates in all worlds. Client cannot override.world-track— this file tracks the world's own release cycle. UCCA may provide templates but the world's version is authoritative.independent— this file has no upstream dependency. It exists only in this world.
Expected Classification Patterns (Hypothesis)¶
Based on au-vet development so far, the likely split:
| Component | Likely Scope | Likely Maintainer | Reasoning |
|---|---|---|---|
| world.config.json | world | shared | UCCA defines schema, client sets values |
| schema/schema.sql | platform | ucca | Canonical tables are universal |
| schema/extensions.sql | world | client | Domain-specific columns and tables |
| api/qualifications.js | platform | ucca | Search/list logic is generic |
| api/verify.js | platform | ucca | Verification engine is the product |
| api/health.js | platform | ucca | Health check contract is standard |
| tools/ingest/*.mjs | world | client | Data sources are domain-specific |
| tools/enrich/*.mjs | world | shared | Enrichment patterns may be reusable |
| tools/validate/*.mjs | platform | ucca | Validation against schema contract |
| assets/branding/ | world | client | Client's visual identity |
| assets/reference/ | world | client | Domain-specific reference data |
| docs/ | world | shared | Documentation is world-specific |
These are hypotheses. The prism exists to validate or refute them as au-vet reaches completion.
Prism Report¶
At any point, a classification report can be generated:
This produces a count of files by scope, revealing the actual platform/world boundary from observed data rather than architectural assumptions.
When to Draw the Line¶
The classification boundary becomes a governance decision when:
- au-vet is feature-complete (all API endpoints, ingestion, UI)
- A second world is being planned (forces the question: what do we copy vs. share?)
- A client requests custom infrastructure (forces the question: what can they change?)
Until then, classify honestly. unknown is a valid and encouraged answer.
12. What This Specification Is NOT¶
- It is NOT a customer onboarding specification (that's a separate document).
- It is NOT a billing model (Layer 2 concern).
- It is NOT a white-label specification (Layer 3 concern).
- It is NOT a FedRAMP compliance document (though it enables FedRAMP by design).
It IS the structural definition of what a world is, what it contains, and how it connects to the platform.
13. Document Control¶
| Version | Date | Author | Change |
|---|---|---|---|
| 1.0 | 2026-03-04 | Tim / Claude | Initial specification |
Version History¶
| Version | Date | Change | Author |
|---|---|---|---|
| 1.0 | 2026-03-04 | Initial draft | Tim Rignold |
| 1.1 | 2026-03-11 | Filed to knowledge site with frontmatter | Claude Code |