/*******************************************************************************
Defines JSON schemas for passport-related data structures, ensuring data integrity and validation.
- Do not handle data persistence or retrieval logic.
- Do not perform runtime data transformations outside of validation.
- Do not manage application state or side effects.
- RFC-1097: step 6 — compass.migrate codemod run
Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.
- RFC-1097: sweep — werkstatt-engine clean
Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.
- RFC-1188: fo-review fix — selectActivePassportKey single-sources the "active key" pick shared by the site generator and the engine resolver
*******************************************************************************/
/**
* @warpgogol/werkstatt-shared/passport — Passport JSON schema (schemaVersion 1.0)
*
* DNA-31 / RFC-0028
*
* This is the authoritative schema for dist/.well-known/cosmic-passport.json.
* Additive changes bump schemaVersion minor; breaking changes require a
* superseding RFC.
*/
import { z } from "zod";
// ---------------------------------------------------------------------------
// Sub-schemas
// ---------------------------------------------------------------------------
const PlanetPinSchema = z.object({
cosmicPlanet: z.string().min(1),
pin: z.string().min(1),
semanticId: z.string().optional(),
});
const StarCompositionSchema = z.object({
route: z.string().min(1),
cosmicStar: z.string().min(1),
planets: z.array(PlanetPinSchema).default([]),
});
const CompositionSchema = z.object({
/**
* SHA-256 hash of the canonical system.yaml content at build time.
* Format: "sha256:"
*/
systemHash: z.string().regex(/^sha256:[0-9a-f]{64}$/),
constellation: z.string().min(1),
biome: z.string().min(1),
stars: z.array(StarCompositionSchema).default([]),
});
const VCProofSchema = z.object({
type: z.literal("Ed25519Signature2020"),
created: z.string(),
verificationMethod: z.string(),
proofPurpose: z.literal("assertionMethod"),
/** Multibase-encoded Ed25519 signature */
proofValue: z.string(),
});
const VerifiableCredentialSchema = z.object({
"@context": z.array(z.string()),
type: z.array(z.string()),
issuer: z.string(),
issuanceDate: z.string(),
credentialSubject: z.object({
id: z.string(),
systemHash: z.string(),
commitSha: z.string(),
}),
proof: VCProofSchema,
});
const ProvenanceSchema = z.object({
commitSha: z.string().min(1),
commitAt: z.string(),
builtAt: z.string(),
buildDurationMs: z.number().int().nonnegative(),
builder: z.string().min(1),
keyVersion: z.string().min(1),
verifiableCredential: VerifiableCredentialSchema,
});
const NebulaPillarSchema = z.object({
score: z.number().min(0).max(100),
weight: z.number().min(0).max(1),
});
const ScoresSchema = z.object({
nebula: z.number().int().min(0).max(100),
pillars: z.object({
performance: NebulaPillarSchema,
accessibility: NebulaPillarSchema,
contentHealth: NebulaPillarSchema,
architecturalCompliance: NebulaPillarSchema,
}),
});
const LinksSchema = z.object({
starMapSvg: z.string(),
publicKey: z.string(),
dnaReport: z.string(),
});
// ---------------------------------------------------------------------------
// Root schema
// ---------------------------------------------------------------------------
export const PassportSchema = z.object({
schemaVersion: z.literal("1.0"),
appId: z.string().min(1),
issuedAt: z.string(),
composition: CompositionSchema,
provenance: ProvenanceSchema,
scores: ScoresSchema,
links: LinksSchema,
});
// ---------------------------------------------------------------------------
// Public key file schema (/.well-known/cosmic-passport-key.json)
// ---------------------------------------------------------------------------
export const PassportPublicKeyEntrySchema = z.object({
version: z.string().min(1),
active: z.boolean(),
type: z.literal("Ed25519VerificationKey2020"),
/** Multibase-encoded (base58btc, prefix "z") Ed25519 public key */
publicKeyMultibase: z.string().regex(/^z[1-9A-HJ-NP-Za-km-z]+$/),
createdAt: z.string(),
});
export const PassportPublicKeyFileSchema = z.object({
schemaVersion: z.literal("1.0"),
appId: z.string().min(1),
keys: z.array(PassportPublicKeyEntrySchema).min(1),
});
// ---------------------------------------------------------------------------
// Identity credentials (RFC-0558)
// ---------------------------------------------------------------------------
export const SiteOwnershipCredentialSubjectSchema = z.object({
id: z.string().min(1),
siteId: z.string().min(1),
role: z.literal("owner"),
});
export const ActorDelegationCredentialSubjectSchema = z.object({
id: z.string().min(1),
siteId: z.string().min(1),
delegatedBy: z.string().min(1),
expiresAt: z.string().datetime(),
scopes: z.array(z.string().min(1)),
});
export const WerkstattCredentialSchema = z.object({
credentialId: z.string().min(1),
type: z.enum(["SiteOwnershipCredential", "ActorDelegationCredential"]),
subject: z.union([SiteOwnershipCredentialSubjectSchema, ActorDelegationCredentialSubjectSchema]),
proof: VCProofSchema,
issuedAt: z.string().datetime(),
issuer: z.string().min(1),
});
export const WerkstattIdentityConfigSchema = z.object({
schemaVersion: z.literal("1.0"),
operatorName: z.string().min(1),
operatorKeyPair: z.object({
publicKeyMultibase: z.string().regex(/^z[1-9A-HJ-NP-Za-km-z]+$/),
keyVersion: z.string().min(1),
algId: z.literal("Ed25519Signature2020"),
}),
authMode: z.enum(["permissive", "enforced"]),
domain: z.string().min(1),
issuedCredentials: z.array(WerkstattCredentialSchema),
revokedCredentialIds: z.array(z.string().min(1)),
});
// ---------------------------------------------------------------------------
// TypeScript types
// ---------------------------------------------------------------------------
export type PassportJson = z.infer;
export type PassportPublicKeyFile = z.infer;
export type PassportPublicKeyEntry = z.infer;
/**
* RFC-1188: pick the active key entry from a parsed cosmic-passport-key.json —
* the single selector both the site generator (context.io) and the engine
* resolver (WorkspaceIO) use so "active key" is defined in exactly one place.
*/
export function selectActivePassportKey(
file: PassportPublicKeyFile,
): PassportPublicKeyEntry | null {
return file.keys.find((k) => k.active) ?? null;
}
export type VCProof = z.infer;
export type VerifiableCredential = z.infer;
export type SiteOwnershipCredentialSubject = z.infer;
export type ActorDelegationCredentialSubject = z.infer<
typeof ActorDelegationCredentialSubjectSchema
>;
export type WerkstattCredential = z.infer;
export type WerkstattIdentityConfig = z.infer;