Exact skill-validation certification¶
The release-grade skill campaign is one current, four-stage contract:
graph-os-generate-skill-runtime-profiledeterministically derives the closed runtime profile from the AgentConfig file and output path named by deployment references.graph-os-generate-skill-certificationderives a strict deployment document from an exact release specification, externally signed promotion evidence, the active AgentConfig document, and an external runtime-profile document.graph-os-certify-skillscreates one checked, in-process HTTPS loopback OIDC authority, starts the selected installedgraph-os, runs the packaged readiness probe from the same release, runs all twenty direct/delegated cases, and publishes signed validation and lifecycle evidence.graph-os-verify-skill-certificationindependently reopens the referenced inputs, checks both signatures, and cross-binds every release, runtime, catalog, process, engine, and validation digest.
No command assumes a release installation directory. The GraphOS executable is
resolved from the deployment-owned JSON argv reference. The running local engine
is discovered only by its unguessable inherited campaign marker, and its open
/proc executable is hashed during the campaign. This works with the current
current/bin release layout without storing that or any other filesystem location
in durable evidence.
External input contract¶
The eight deployment references and two authority controls are first-class,
current-only AgentConfig fields. Configure the references in the active XDG
config.json; the authority controls have safe self-contained defaults. There
are no alternate field names or untyped call-site-only certification settings:
| AgentConfig key | Typed value | Purpose |
|---|---|---|
SKILL_CERT_RUNTIME_CONFIGURATION |
absolute path string | Active XDG AgentConfig input |
SKILL_CERT_RUNTIME_PROFILE |
absolute path string | Generated closed runtime profile |
SKILL_CERT_RELEASE_SPEC |
absolute path string | Exact-local release specification |
SKILL_CERT_PROMOTION_EVIDENCE |
absolute path string | Signed successful promotion evidence |
SKILL_CERT_GRAPHOS_ENDPOINT |
loopback HTTP(S) URL | Active GraphOS MCP endpoint |
SKILL_CERT_GRAPHOS_COMMAND |
JSON argv array | Exact installed graph-os start command |
SKILL_VALIDATION_EVIDENCE_SIGNER_COMMAND |
JSON argv array | External evidence signer command |
SKILL_VALIDATION_EVIDENCE_VERIFIER_COMMAND |
JSON argv array | External evidence verifier command |
SKILL_CERT_IDENTITY_AUTHORITY_MODE |
ephemeral-https-loopback |
Lifecycle-owned certification authority |
SKILL_CERT_IDENTITY_TOKEN_TTL_SECONDS |
integer, 180–3600 | Renewable token lifetime; default 300, subject to the computed campaign-window floor |
The numeric 180–3600 range is only the authority's structural bound. A generated
deployment also fails closed unless the lifetime covers its maximum case timeout,
the current trace precheck/export/ingestion windows, shutdown grace, and the lease
expiry safety margin. With the current default 120-second case timeout,
30-second trace window, and 30-second shutdown grace, the computed minimum is
245 seconds; the default 300 therefore remains valid. The floor is recomputed
when campaign timeouts change rather than being treated as a second fixed setting.
AgentConfig performs structural validation only: paths must be bounded and
absolute, the endpoint must use HTTP or HTTPS with a literal loopback address or
localhost, and commands must be bounded JSON argv arrays whose executable is an
absolute path. It does not touch deployment material while parsing configuration.
The skill_certification doctor check owns availability proof: each path must
resolve to a bounded, single-link regular file, the configuration and endpoint
must be the active ones, the start executable must resolve to exact graph-os,
and all three commands must resolve to executable, non-symlink, non-shell regular
files. The check never returns a path, endpoint, command, credential, or file
content.
Run the isolated readiness check before generating or running a campaign:
It skips only when all eight references are unset, fails closed for partial, invalid, or unavailable material, and passes only when the complete deployment boundary is ready.
The generator consumes four bounded absolute regular files:
- the exact-local release specification;
- its signed successful promotion evidence;
- the exact active XDG
config.json; and - a deployment-owned
SkillValidationRuntimeProfiledocument.
The profile document is deliberately closed and contains no environment values:
{
"apiVersion": "graphos.io/v2",
"kind": "SkillValidationRuntimeProfile",
"configurationDigest": "sha256:<digest>",
"modelRegistryDigest": "sha256:<digest>",
"identityAuthority": {
"mode": "ephemeral-https-loopback",
"tokenTtlSeconds": 300,
"tlsVerificationRequired": true,
"lifecycleOwned": true,
"renewableCredentialsRequired": true
},
"engineTopology": "local-autostart",
"observability": "metadata-only",
"sequential": true
}
Do not hand-author or commit this document, or commit a generated deployment for a particular environment. Keep both in deployment-owned configuration. Generate the profile through reference names already present in AgentConfig:
graph-os-generate-skill-runtime-profile \
--configuration-reference SKILL_CERT_RUNTIME_CONFIGURATION \
--profile-reference SKILL_CERT_RUNTIME_PROFILE
The configuration reference must resolve to the bounded absolute AgentConfig JSON
file; the profile reference resolves to its external JSON destination. The command
publishes deterministic, mode-0600 JSON and reports no paths or configuration
values. The generated
SkillValidationDeployment contains only digests, bounded numeric controls,
booleans, and environment-variable names. It contains no command argv, endpoint,
credential, identity, profile content, certificate material, or filesystem path.
The generator checks the release evidence signature before producing output. It
also recomputes the release-specification, promotion-evidence, GraphOS,
configuration, and profile digests. It independently attests the installed release
closure and writes these mandatory fields inside the deployment's top-level
release object:
{
"agentUtilitiesSha256": "sha256:<digest>",
"agentUtilitiesFileCount": 10,
"distributionClosureSha256": "sha256:<digest>",
"releasePythonSha256": "sha256:<digest>"
}
The count shown is the schema minimum, not a fixed release count. The generator
derives all four values from the checked promotion evidence and installed release;
they are not operator-supplied CLI values. The configuration must describe exactly
one light and one normal chat model. Both models must:
- use either a literal loopback/private address or an exact private DNS name
present in
MODEL_HTTP_ALLOWED_PRIVATE_HOSTS; - use only HTTP or HTTPS without embedded credentials, query, or fragment; and
- have reference-backed API-key, OAuth2-secret, or header material.
Before any service starts, private DNS must resolve to exactly one loopback, RFC1918, or IPv6 ULA address. The governed request transport independently resolves and pins every call, retains logical Host/SNI for hostname verification, checks the connected peer, and rejects public or ambiguous rebinding. Public, unreferenced, missing, duplicate-tier, or ambiguous model entries are rejected. Only a canonical model-registry digest and aggregate booleans/counts are retained; model identifiers, DNS names, and addresses are not.
Generation¶
All *Reference options below are environment-variable names. At certification
time the material references resolve to absolute regular files, the start/signer/
verifier references resolve to bounded JSON argv arrays, and the endpoint reference
resolves to the active loopback GraphOS URL.
graph-os-generate-skill-certification \
--release-id release-<id> \
--release-specification <external-spec> \
--promotion-evidence <external-promotion-evidence> \
--runtime-configuration <external-config-json> \
--runtime-profile <external-profile-json> \
--output <external-deployment-json> \
--specification-reference SKILL_CERT_RELEASE_SPEC \
--promotion-evidence-reference SKILL_CERT_PROMOTION_EVIDENCE \
--configuration-reference SKILL_CERT_RUNTIME_CONFIGURATION \
--profile-reference SKILL_CERT_RUNTIME_PROFILE \
--endpoint-reference SKILL_CERT_GRAPHOS_ENDPOINT \
--start-command-reference SKILL_CERT_GRAPHOS_COMMAND \
--signer-command-reference SKILL_VALIDATION_EVIDENCE_SIGNER_COMMAND \
--verifier-command-reference SKILL_VALIDATION_EVIDENCE_VERIFIER_COMMAND
The normative deployment schema is
deploy/release/skill-validation-deployment.schema.json.
The campaign does not require an external identity provider. The orchestrator
generates a private CA, loopback server certificate, opaque client credentials,
and asymmetric JWT key for that run. It projects only env:// secret/profile
references into the exact GraphOS, readiness, and validator child environments;
it neither rewrites AgentConfig nor places runtime endpoints, credentials,
certificate material, or temporary locations in evidence. TLS verification has
no disable switch.
Readiness and lifecycle execution¶
graph-os-skill-readiness is the packaged probe invoked as a short-lived process
from the exact release by the orchestrator. Do not start it separately during an
exact campaign: only graph-os-certify-skills owns the authority and complete
zero-to-one-to-zero lifecycle. The probe proves:
- the referenced configuration is the active XDG AgentConfig file and still has the signed private/local model-registry digest;
- every private-DNS model resolves uniquely inside the private boundary enforced by the pinned request transport;
- the endpoint is the active loopback GraphOS endpoint;
- the selected named TLS profile resolves with peer and hostname verification;
- the configured outbound MCP identity mode is complete;
- authenticated GraphOS discovery exposes
graph_orchestrate,graph_query, andgraph_jobs; - a governed zero-row query succeeds; and
- engine resolution is local, never a configured remote topology.
Run the campaign with adjacent output destinations:
graph-os-certify-skills \
--deployment <external-deployment-json> \
--report <external-report.md> \
--validation-evidence <external-validation.json> \
--lifecycle-evidence <external-lifecycle.json>
Before service startup, the orchestrator re-checks the signed promotion evidence and recomputes the specification, promotion, GraphOS, configuration, profile, model-registry, Agent Utilities tree, distribution closure, and release-Python digests plus the Agent Utilities file count. A passing lifecycle proves all of the following:
- the in-process HTTPS OIDC authority:
0 → 1 → 0; - its private CA and server key existed only in private ephemeral work and were removed before evidence signing;
- peer and hostname verification succeeded and at least two renewable credentials were minted without retaining tokens, identities, endpoints, or certificates;
- all private-DNS models resolved uniquely to private addresses and the request transport's public-rebinding guard was active;
- global GraphOS processes:
0 → 1 → 0; - marker-qualified candidate GraphOS processes:
0 → 1 → 0; - marker-inherited local engine processes:
0 → 1 → 0; - terminal native Langfuse MCP child process count:
0; - terminal loopback OIDC fixture process count:
0; - the running engine executable digest equals the promoted engine digest;
- the candidate and marked engine were stopped and reaped;
- the validator exited zero; and
processGate.installedReleaseAttestedis exactlytrue;- the signed validation evidence contains exactly twenty passing cases and is bound by its exact file digest.
The normative lifecycle schema is
deploy/release/skill-validation-deployment-evidence.schema.json.
Validation evidence¶
The validator receives release, GraphOS, engine, configuration, profile, and model registry digests only from the already checked deployment. Its signed subject binds the exact one-skill catalog, canonical test catalog, both case digests, direct/delegated execution, configured model class, exact skill body, one metadata-only Langfuse lookup, and one governed parent-graph trace readback per case. Passing evidence requires two cases, one complete direct/delegated pair.
The two development cases also bind one externally supplied, digest-bound
RF-021 candidate identity. Their retained architecture evidence contains exactly
three content-free tool observations: an authoritative component/capability join,
advisory discovery parsed from the existing flat-text graph_search contract with
its exact single-target connection trailer, and a caller row grounded by the same
file/line citation. The discovery record must
carry the source identity, authority signature, and a digest over that exact text
contract; a synthetic structured dictionary is not accepted. It also records the
twelve structured RF-021 scenario outcomes. Proposal,
non-authoritative, stale, duplicate, unrelated, text-only, missing-target,
unbounded-owner-root, ungrounded-caller, and incomplete replacement/deletion
evidence cannot produce a passing case. Concrete runtime identity labels are not
retained; only the externally governed policy digest is bound.
The immutable RF-019 source-acceptance result (641c780f42db1187ddf377d26b81ff553f5ffacb,
tree cb222da...) is a CA/refactor reference-plane input only. Its qualification
state remains PROPOSED/NOT_RUN; it does not establish runtime acceptance, and
the external /etc authority bundle is deferred until post-refactor deployment.
flowchart LR
C[Digest-bound candidate] --> Q[graph_query exact component/capability join]
C --> S[graph_search advisory discovery]
C --> G[graph_code grounded live callers]
Q --> V[RF-021 typed validation]
S --> V
G --> V
V --> E[Signed content-free architecture evidence]
V -->|missing or stale| H[Owner manifest regeneration and source_sync delta handoff]
The normative validation schema is
deploy/release/prebundled-skill-validation-evidence.schema.json.
Independent verification¶
graph-os-verify-skill-certification \
--deployment <external-deployment-json> \
--validation-evidence <external-validation.json> \
--lifecycle-evidence <external-lifecycle.json>
The verifier does not trust the producer's earlier verification result. It resolves
the verifier JSON argv through
deployment.validation.verifierCommandReference, sends canonical signed JSON on
standard input, and requires exactly:
{
"verified": true,
"subjectDigest": "sha256:<canonical-unsigned-subject-digest>",
"keyId": "key:<opaque-key-digest>"
}
It then independently checks both JSON schemas, current catalog digests, all deployment bindings, the four installed-release attestations and file count, the validation file digest, and the passing lifecycle invariants. A fixed verifier command, shell command, literal key, unsigned subject, retired v1 document, or alternate response shape is rejected.
All durable evidence is content-free and path-free. It stores no prompt, model output, source content, endpoint, credential, identity, raw trace identifier, profile value, command, or filesystem location.