Repository credential tests
Human verified
A human reviewed this page, but it may be out of date. Later edits may not have been reviewed.
Overview
Use these checks to verify repository credential changes at the source, package, container, platform, or live-provider boundary. Run commands from the repository root with Node.js 24, Git, OpenSSL, Docker, and installed workspace dependencies. The controlled tests use disposable fixtures and do not use ambient GitHub credentials.
Run controlled tests
node scripts/verify-repository-credentials-boundary.tsnode --test tests/conformance/repository-credentials-fixture-ownership.test.ts \ tests/conformance/repository-credentials-backend-conformance.test.tsnode --test tests/integration/repository-credentials-git.test.ts \ tests/integration/repository-credentials-native-paths.test.ts \ tests/integration/repository-credentials-service-loss.test.tsThe source Git tests require a node:24-bookworm image and gh 2.103.2
at /usr/bin/gh. Override these with REPOSITORY_CREDENTIALS_NODE_IMAGE and
REPOSITORY_CREDENTIALS_GH_BINARY. Missing prerequisites fail the tests. The
fixtures use a controlled provider and verified TLS; they do not prove live GitHub
access. The gh workflow requires the combined qualification image
because push-policy sessions require installed client hooks. Prepared token renewal
is exercised by the worker Token Service suites.
The source boundary check also runs in pnpm check:workspace. Changes to its
privileged allowlists require security review of the authority, caller, scope,
and negative coverage. It is a regression guard, not a sandbox or a dataflow proof.
The separate public GitHub reader owns an HTTP listener and permits anonymous HTTPS GET requests to a fixed origin. The source guard forbids imports between the reader and credential owners; its boundary test uses a local TLS provider. PR CI's Image Runtime Startup lane checks that stock Codex reads the projected skill through its limited native proxy, with local binding disabled, and returns a random title available only at the TLS provider. This needs no model or repository credentials.
Full Integration's Gateway Routing journey checks the dedicated Agent, managed skill, and native network path with a substituted external provider. The Agent must return a pull request title absent from its prompt. Record a pass with no skips on the reviewed source. The hosted lane accepts only approved main versions; verify the full conversation and cluster policy there or in an authorized equivalent environment.
For native selection and routing, run:
node --test tests/integration/repository-credentials-client-config.test.ts \ tests/integration/repository-credentials-router.test.tsProtected repository metadata reads
checks-baseline-2 runs the metadata response test
with the real route policy, upstream sender, and a loopback TLS origin. An independent
socket observer captures the decrypted request and the origin response through EOF.
Two client processes read through FIN and receive only the configured repository identity.
The test refuses changed routes and GET bodies before they reach the origin.
On a successful read it strips synthetic credentials reflected in headers and body.
A forbidden final trailer yields the exact exchange-uncertain response, while
ordinary reads still accept benign trailers. The dispatch gate is a fixture.
For authenticated sibling execution, joined authorization, and the response OpenShell
actually delivers, use the installed custody qualification.
Verify Agent admission and durable ownership
Build before running the source and materialization checks:
pnpm buildnode --test tests/integration/repository-credentials-admission.test.mjs \ tests/integration/repository-credentials-driver.test.ts \ tests/integration/repository-runtime-materialization.test.ts \ tests/integration/repository-credentials-router.test.tsFor durable session and recovery checks, prepare a migrated disposable database
with an application role as described in PostgreSQL testing.
Run postgres-repository-sessions.test.ts,
postgres-repository-broker-receipts.test.mjs, and the relevant restart and
worker version tests with OCC_TEST_DATABASE_URL set. The
postgres-openshell-standing-selected-repository.test.ts case follows one
github-repository binding through approval, deployment, its original session
deadline, changed-recipient refusal, successor issuance, and withdrawal. A separate
issuer with standing permission removed must refuse issuance. It uses the real PostgreSQL worker
and credential owner with controlled OpenShell and GitHub protocol peers.
These checks do not prove a running Kubernetes Pod or model turn.
The final custody check moves only stored provider timestamps past verified expiry
and clock skew; it asserts material erasure without a revocation request.
Qualify emitted artifacts
pnpm credentials:buildnode --test tests/integration/repository-credentials-package.test.tsREPOSITORY_CREDENTIALS_APP_ROOT="$PWD/.build/repository-credentials/client/dist" \ node --test tests/integration/repository-credentials-router.test.tsThis verifies the emitted service and client without workspace source or runtime
node_modules, including hooks reached through relative symlinks after package
relocation. The router run uses the generated hook launchers for native Git checks.
To test those artifacts together, build both images as described in
the operator guide,
then run:
docker build --builder default --load --pull=false \ --build-arg SERVICE_IMAGE=repository-credentials:local \ --build-arg CLIENT_IMAGE=repository-credentials-client:local \ -f tests/fixtures/repository-credentials/Dockerfile.qualification \ -t repository-credentials-qualification:test .REPOSITORY_CREDENTIALS_TEST_IMAGE=repository-credentials-qualification:test \ node --test tests/integration/repository-credentials-container.test.ts \ tests/integration/repository-credentials-gh.test.tsThe combined suite runs the emitted service/client cases, native Git paths, pinned
gh REST actions (including pull requests), and common-backend conformance against
controlled peers. It mounts only tests from the workspace and uses controlled
credentials. The client uses its installed hooks. No GitHub credentials are required.
The Compose check only renders the configuration; it does not start the services.
An unset image selector skips the container cases.
Check the runtime image's private material volume
Build the runtime image from the candidate source and follow the runtime volume test prerequisites:
OCC_TEST_RUNTIME_IMAGE=openclaw-enterprise-runtime:test \ node --test tests/integration/repository-runtime-volume.test.tsThis tests the image-installed client and Docker mounts. An unset selector skips
the test; the images-packaging CI lane requires it to run.
Verify separate running containers
With both delivered images built, run:
REPOSITORY_CREDENTIALS_SERVICE_IMAGE=repository-credentials:local \REPOSITORY_CREDENTIALS_CLIENT_IMAGE=repository-credentials-client:local \ node --test tests/integration/repository-credentials-isolation.test.tsThe test checks credential custody and Git/gh access through separate running
containers against a controlled provider. It does not prove network confinement
or live GitHub access. Supplying neither selector skips the test; supplying only
one fails it. Record both image IDs and the cleanup result.
Verify prepared native Git
Run node --test tests/integration/repository-native-cutover.test.ts for controller
selection, real Unix control requests, prepared receipt binding, development-token
rejection and v1 recovery. This uses the in-memory State adapter and no provider.
PostgreSQL custody, old signing receiver rejection, stock images, native Git and
protected runtime behavior require separate integration evidence.
The installed prepared Git lane uses a dedicated Codex Agent in a fresh installation with controlled private Git and model peers. Its authorized run proves the packaged sender in a real cluster; it is separate from ordinary CI. The PostgreSQL tests cover receipt recovery and no-replay behavior, while the runtime image tests cover stock Codex and generated client material. These checks do not replace the installed lane.
On a native-command chat completion mismatch, the lane attempts to report matching synthetic model request/result counts and whether any result contained the completion marker, or state that model observations are unavailable. A separate message confirms binding withdrawal and discovery release when that checkpoint was recorded. Without that message, the stage is unknown. These diagnostics do not expose chat or command output and do not replace the Git assertions or qualify the release. The failure summary prefers the runner's failed-case or file-failure record over generic lane issues. It publishes only known source coordinates and fixed error categories; absent or malformed records retain the bounded fallback summary.
Receiver failures distinguish transport, interrupted response bodies, and invalid
JSON without printing response content. A failed kubectl exec reports
gateway-exec with its available exit code or signal. Model observations are
best-effort: unavailable or replaced log history appears as unknown, and each
optional model or Pod log read has a ten-second timeout. Diagnostic failures do
not replace the failed request. The receiver category and HTTP status remain in
the runner summary even when the optional journey log cannot be written or parsed. These categories identify where the check failed;
they do not establish why the Gateway or native command failed.
To bind its receipt to a selected OCE release,
prepare an independent JSON control file with sourceSha (the full OCE checkout SHA)
and images.controller, images.runtime, and images.repository (the broker), each
an immutable sha256:<64 lowercase hex characters> built manifest digest. Obtain
these expected values from the release selection, not from the receipt being checked.
From that release checkout, run:
node scripts/ci/run-tests.ts aggregate skipper-prepared-git-installed \ --results-dir /path/to/results --release-selection /path/to/release.jsonThe consumer requires the selected SHA, all three built digests, recorded imported
manifest and config digests, the complete chat/Git/withdrawal journey, and successful
test and cluster cleanup. Missing control, release fields or proof fails qualification;
a generic runner summary is insufficient. Success adds releaseQualification to the
aggregate. Without --release-selection, normal smoke aggregation remains unchanged
and does not qualify a selected release.
The prepared runtime includes an added synthetic-model CA trust layer. Its recorded
runtime digest identifies that prepared image, not the underlying stock or published
runtime image. Qualification applies only to the exact selected digest set under
checkout-images-with-synthetic-model-trust-layer; it cannot establish qualification
of a different published image set, even at the same OCE commit.
The controlled model waits for a yielded native command with write_stdin on the
same session, within the existing 170-second chat deadline. It never replays the
command. Acceptance still requires terminal success, the exact completion marker,
and the independent native and Git observations. A completion mismatch reports
only status, exit code, session presence and poll count; raw command output stays
private. Offline model-adapter cases in skipper-private-git-origin.test.mjs check
the pinned Codex function-tool envelopes; they do not prove installed execution.
Run node --test tests/integration/skipper-release.test.ts for positive and adverse
offline checks through the actual aggregate CLI. They do not execute an installed journey.
Verify OpenShell Git expiry and restart
The installed retention case
uses the ordinary authenticated OpenShell installation, a dedicated Codex Agent,
and an openai CredentialSource. Its native startup probe uses the authorized
OPENAI_API_KEY and OCC_TEST_OPENAI_MODEL; model responses are not simulated.
Git and App issuance use a private HTTPS fixture with real git-http-backend.
No live GitHub repository or ambient GitHub credential is used.
The case selects a finite 600-second repository grant and requires successful authenticated Git and a real model response before the API's returned deadline. After the grant expires and the worker withdraws access, the same revision, Sandbox and runtime containers must complete a file operation and another model response while a fresh Git request fails without reaching the origin. The case restarts the installed worker with persisted PostgreSQL state and custody material, then repeats those observations. It does not adjust clocks or queue schedules.
The fixture owns its loopback Kubernetes installation and cleanup. Its supervisor
trust image adds only the private origin's public CA; the executable must match
the pinned stock image. Record the tested source, image digests and each
observation. The lane's result artifact retains these receipts under
files[].measurements, bound to its sourceSha and the selected test file.
Receipts contain digests, Kubernetes UIDs, counters and fixed outcomes; opaque
runtime identifiers use SHA-256 fingerprints. The final cleanup receipt is
emitted only after all owned resources are removed. This proves the selected installation and controlled Git boundary,
not live GitHub access or a different published image set.
An unsuccessful expiry wait retains bounded worker outcomes and polling counters;
these diagnostics do not establish successful withdrawal or runtime retention.
A failed retained-execution check records before/after origin counters and whether the origin snapshot changed. Its managed-Exec exit code identifies the failed check without retaining Git output:
| Code | Failed check |
|---|---|
| 41 | Original identity file contents |
| 42 | File write |
| 43 | File readback |
| 44 | Git executable availability |
| 45 | Git unexpectedly succeeded |
| 46 | Git could not execute (126 or 127) |
| 47 | Failed Git returned nonempty stdout |
Stock mediates workload connections before HTTP. The test requires a supervisor
transparent_tcp_policy_denied event for github.com:443 and the measured Git
executable, immediately preceded by the warning that the endpoint is not allowed
by any policy. After Git exits, a normal filtered DNS lookup of a fresh absolute
.invalid. name supplies an ordered end marker; lookup status is not proof.
The reader waits through that exact marker, checks log continuity through every
poll, and rejects observed competing or unpaired staged denials in the Git window.
Unchanged supervisor identity excludes foreign events. No other client calls
github.com:443 during the isolated attempt.
These observations accompany failed Git, successful file operations and unchanged origin counters. The event has no Exec request ID or process ID. Missing markers, pairs or retained history fail qualification, but stock producer drops are undetectable: this is bounded observed evidence, not a lossless record of every connection’s cause. Raw logs and Git output are not retained in result receipts.
The diagnostic receipts do not replace successful shell operations, the explicit policy denial and unchanged-origin assertions.
The case is registered in the openshell lane. For a reviewed same-repository PR,
a maintainer selects QA Matrix Advisory with full-qa.
The existing environment supplies credentials inside the job. The narrower
qa-openshell-compose label does not run this case. A complete, non-skipped pass
and successful cleanup are required; registration alone is not qualification.
Controller and broker image compatibility probe
Run the image-pair-qualification lane using the
image-pair procedure. It stages
current and incompatible older controller and broker images against disposable
fixtures, checks the admission protocol, and rejects incompatible pairs. It does
not prove credential disposal or a live Agent workflow. See the
qualification test
for fixture setup and expected probe exchanges.
Run an authorized live smoke
Use an explicitly selected development-token sender
with valid DNS and TLS on port 443, its private control socket and public CA, pinned clients,
and a disposable repository authorized for temporary branch, pull request, issue and comment
writes. Configure exactly pushRefAllowlist: ["refs/heads/credential-smoke/*"]:
REPOSITORY_CREDENTIALS_LIVE=1 \REPOSITORY_CREDENTIALS_LIVE_AUTHORIZED=1 \REPOSITORY_CREDENTIALS_LIVE_CONTROL_SOCKET=/run/credential-service/control.sock \REPOSITORY_CREDENTIALS_LIVE_CA=/run/credential-service/public-ca.pem \ node --test tests/integration/repository-credentials-live.test.mjsThis exercises a real provider through the development-token sender, not OCC Agent admission or a model. The static token stays in the sender. The test creates unique resources and attempts cleanup with a timeout. Ambiguous or incomplete cleanup fails the test: reconcile the reported run marker and repository manually. A closed session is not disposed until its active and pending credential obligations are resolved. An unset selector skips the test; selecting it without required authorization or inputs fails.
Qualify an installed Agent against GitHub
The former direct repository-credentials-installed lane has been removed.
Use the maintained QA matrix for an authorized installed
Agent's real Git exact-ref journey. It requires an authorized disposable repository
and independent provider readback. Verify that the granted branch points to the
expected commit, that the push outside the granted branch was refused, and that
credential disposal and cleanup succeeded. Its
git-only grant opens no pull request. A direct container command or ready Pod
does not prove an Agent model turn.
Separately, use the installed prepared Git qualification for the real installation with controlled Git and model peers, bound to the selected source and image digests. That qualification does not prove live GitHub access; QA evidence does not replace its release qualification. Removing the old lane adds no new live proof.
Record each evidence boundary
Record the source commit, selected test and pass/fail/skip counts, artifact and image IDs where applicable, and cleanup results. A skip is not a pass. Source, packaged artifacts, controlled provider, separate containers, installed Agent, and live provider results establish different things; do not substitute one for another. Historical results apply to the artifacts that produced them.
The native package excludes App signing and token issuance. Its detached package
checks cover prepared configuration and explicit development-token clients.
The prepared native workflow is verified in
tests/integration/postgres-prepared-repository-git-broker.test.mjs, including
exact-ref enforcement, draft creation, response loss and no replay. That suite
requires real PostgreSQL; package checks and simulated providers do not replace it.
