Reference
Prebound Crossing Authority (Preview)
Operate the first signed-grant carrier on a protected self-hosted runner without moving authority into the repository.
Recommended next
Use this when
Use this preview carrier when a controlled self-hosted runner must execute one heavier non-agent lane only after independently managed signed authority admits its exact Ota scope.
Do not use it for routine verification, agent-mode execution, or a GitHub-hosted job that can create its own authority files.
- the repository declares only an authority identifier
- a platform administrator owns the runner boundary and fixed trust material
- an independent provisioner owns signing, revocation, and sequence advancement
- Ota verifies authority before setup, provisioning, child processes, services, or task mutation
Trust boundary
The first carrier is prebound_file. It is a filesystem boundary for Ota's current unprivileged process, not a hosted approval system or provider-attested privilege boundary.
- repository files, workflow YAML,
OTA_POLICY, environment variables, and CLI flags cannot select the authority store, bundle path, issuer, or key - the runner user can read authority state but cannot write it or its parent directories
- Ota reports this carrier as
authority_separation_posture: current_process_filesystem_guarded, not as provider-attested separation - a runner that has sudo, host capabilities, namespace control, or an injected writable mount cannot claim stronger authority separation from this carrier alone
- GitHub-hosted runners must not self-provision this state and then claim independent authority
Ownership model
Repository
Declares only authority_id and requests a named grant. It never carries keys, bundles, sequence state, or trust paths.
Provisioner
Owns the signing key, fixed trust binding, signed bundle, revocations, and monotonic sequence state outside the repository and job.
Runner
Runs Ota as an unprivileged user, verifies authority read-only, and writes only runner-owned crossing evidence after admission.
Linux runner layout
A platform administrator installs this layout before the runner accepts a job. Every file is regular, every parent is root-owned and not group/world writable, and the runner user can only read the files it needs.
/etc/ota/crossing-authorities.jsonidentifies the authority, issuer/key fingerprint, allowed contract identities, bundle path, sequence-state path, and freshness bounds- the signed bundle carries grants, revocations, issue/freshness times, sequence, and Ed25519 signature
- the sequence state prevents rollback to an older signed bundle
- the signing private key stays with the provisioner and is never installed in the runner image
- macOS uses
/Library/Application Support/Ota/crossing-authorities.json; Windows currently refuses this carrier until equivalent ACL verification exists
/etc/ota/ crossing-authorities.json fixed trust-store bindings/var/lib/ota/ crossing-authority.json signed grant bundle crossing-authority-sequence.json sequence and clock high-water stateHarden the runner image
Build or maintain the self-hosted runner image separately from the repository, then provision authority state through an administrator-owned path. The job user must be non-root and must not retain a path to rewrite or remount authority state.
- remove passwordless sudo and administrative group membership from the runner user
- do not expose a Docker socket or privileged host-control path to the job unless that capability is separately modeled and attested
- install Ota and the fixed trust binding before the runner starts accepting jobs
- publish the signed bundle and sequence state through a root-owned image layer or protected platform mount before assigning a job; the job only receives read access
- register a protected runner label such as
ota-crossing-live; repository workflow selection does not create the authority boundary - rebuild or reprovision the runner when the administrator rotates trust material; do not let a workflow write replacement files
Prepare a dedicated VPS runner
Use a dedicated Linux/x64 VPS for controlled pressure or operator validation. GitHub Actions schedules the reviewed workflow on that host; it does not issue or host crossing authority.
- restrict SSH to the administrator, keep the host dedicated, and retain persistent disk state for the provisioner-owned sequence record
- do not grant
ota-runnersudo, Docker, or other host-control groups; a matching local inspection still proves onlycurrent_process_filesystem_guarded - build the exact reviewed Ota commit from a clean Core checkout, install it root-owned on
PATH, and requireota --version --jsonto match the contract'sagent.bootstrap.ota.source.rev - in GitHub repository Settings > Actions > Runners, register the runner as
ota-runnerusing GitHub's time-limited Linux/x64 registration commands, then assign only the reviewed repository and one scenario label such asota-crossing-live - the independent provisioner derives scope from Ota output and publishes root-owned signed authority state separately; the signing key never enters the VPS, repository, workflow, or job environment
- run
ota authority inspect --jsonasota-runnerbefore dispatch; archive that result and the Ota version JSON with every pressure run
sudo useradd --create-home --shell /bin/bash ota-runnersudo install -d -o root -g root -m 0755 /etc/ota /var/lib/otaInspect the fixed boundary
Use Ota's diagnostic-only hardening profile before live grant pressure. It consumes the same fixed-path protected-file verifier as admission but cannot select a grant or create authority.
- require every observation with
required: trueto reportstatus: passed - retain passwordless sudo, namespace control, alternative container endpoints, provider metadata credentials, and broader escalation as explicit unknowns when Ota cannot observe them safely
- only
matched_with_unknownsexits zero; incomplete, failed, and unsupported reports remain schema-valid JSON - a matched report proves only
current_process_filesystem_guarded, not a grant, crossing record, hardened runner, provider attestation, or administrator identity - public diagnostics redact protected paths, keys, signatures, bundle contents, and grant identities
ota authority inspect --jsonPublish authority
The provisioner first obtains Ota's machine-readable refusal for the ungranted lane, then derives authority from that exact contract and semantic scope. After publishing the grant, it verifies admission with a separate non-consuming preview.
- before a grant exists, expect a typed
crossing_grant_requiredrefusal withexecution_started: false; use its derivedscope_identityandcontract_identityas issuance inputs - bind each grant to contract identity, semantic scope identity, crossing family, classification, actor posture, action/resource, and bounded validity
- derive identities and Ed25519 signatures from Ota's canonical domain-separated JSON rules; never hand-type a digest or signature
- publish the signed bundle and matching monotonic sequence state as one controlled authority operation
- after publication, a successful dry-run returns
crossing_grant_admission.decision: admissible_not_consumedwithout creating a crossing transaction - Ota verifies signature, issuer/key, freshness, revocation, scope, and sequence before execution; it never writes or repairs authority state
ota run publish --dry-run --jsonota run publish --grant approved-publish --dry-run --jsonContract and workflow
- the workflow selects a runner; it does not install keys, bundles, or authority state
--grant <id>is explicit and Ota-owned; it cannot bypass agent safety or authorize a routine lane- keep the runner label protected by platform administration rather than treating a YAML label as proof of hardening
governance: crossing_authority: authority_id: platform-release-authorityjobs: publish: runs-on: [self-hosted, linux, ota-crossing-live] steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 - run: ota run publish --grant approved-publishVerify before and after execution
- a successful preview returns
crossing_grant_admission.decision: admissible_not_consumedand starts no crossing transaction - real execution repeats sensitive admission checks, then creates a fresh runner-owned crossing transaction before selected-lane work
- the receipt/archive binds authority, grant, bundle, semantic scope, and terminal transaction; history re-derives the archived decision instead of trusting a lane label
- a successful crossing record is evidence of that execution only and never reusable authority
ota run publish --grant approved-publish --dry-run --jsonota run publish --grant approved-publish --receiptota receipt --history --jsonRefusal outcomes
Missing or unavailable
No fixed store, bundle, key, protected sequence state, or trustworthy clock posture: Ota refuses before work starts.
Stale, expired, or revoked
An outdated bundle, elapsed grant, or signed revocation is a typed pre-execution refusal.
Out of scope
A renamed or expanded closure, changed platform, mode, effects, or contract cannot reuse a grant issued for an earlier scope.
Limits of this preview
- crossing authority governs only execution admitted through Ota; it cannot prevent a developer, agent, or workflow with unrestricted shell access from invoking the underlying command directly
- non-optional enforcement therefore also requires an adopted chokepoint, such as a sandbox or capability boundary that exposes only admitted Ota lanes, or a mandatory merge gate that rejects bypassed execution evidence
- no GitHub-hosted self-provisioning claim
- no provider-attested privilege separation or verified human/CI identity
- no broker-backed, nonce-bound, atomically consumed one-use work-unit lease
- governed runtime and lifecycle proof refuse before start until one terminal crossing transaction can cover their complete invocation set
- no public Ota signing CLI; authority issuance remains an independently operated and reviewed platform responsibility