{"schemaVersion":"developer.reits.tech/runner-factory-gitea-control-plane/v1","status":"ADAPTER_IMPLEMENTED_NOT_CONFIGURED","observedAt":"2026-07-20T17:55:00Z","scope":{"baseUrl":"https://gitea.reits.tech","organization":"reits","repositoryPattern":"reits/<admitted-repository>","credentialSelection":"SECRET_REFERENCE_ONLY","agentSocket":"unix:///run/reits-runner/agent.sock","allowedLabels":["ubuntu-latest"],"maxJobs":1},"truth":{"runtimeDriverConfigured":false,"controlCredentialConfigured":false,"workerAgentInstalled":false,"liveRunners":0,"runtimeAssignments":0,"giteaReadsExecuted":0,"giteaWritesExecuted":0,"registrationSecretsRecorded":0,"runnerCredentialsRecorded":0,"readinessGateSatisfied":false,"paidResourcesCreated":false,"deploymentPermitted":false},"implementation":{"adapter":"ops/runner-factory/gitea-control-plane.mjs","testDriver":"ops/runner-factory/memory-gitea-control-driver.mjs","fixtureRegistry":"ops/runner-factory/gitea-control-plane-fixtures.json","verifier":"scripts/verify-runner-factory-gitea-control-plane.mjs","runtimeDriver":"NOT_CONFIGURED"},"operations":[{"id":"registerEphemeral","input":"cloud-closed worker + mutable one-time token bytes + exact org/repo/job/plan/labels","proof":"worker-agent attestation + org-scoped Gitea runner GET","failure":"retire unemitted runner or report cleanup unproven"},{"id":"verifyAssignment","input":"opaque runner capability + admitted job + maxJobs=1","proof":"repo job GET binds runner_id/name + root agent removes reusable file and holds one exact-job memory lease","failure":"FAILED_NEEDS_DELETE"},{"id":"deleteRunner","input":"opaque runner capability","proof":"org runner DELETE returns 204/404 + root agent destroys credential and assignment state","failure":"FAILED_NEEDS_DELETE and retryable"}],"modeledCalls":[{"boundary":"worker-agent","operation":"RegisterRunner","authority":"one-time mutable token bytes","recorded":false},{"boundary":"gitea-rest","operation":"GET /orgs/reits/actions/runners/{runner_id}","authority":"control credential reference"},{"boundary":"gitea-rest","operation":"GET /repos/{owner}/{repo}/actions/jobs/{job_id}","authority":"control credential reference"},{"boundary":"worker-agent","operation":"SealAssignment","authority":"root-owned unix socket"},{"boundary":"gitea-rest","operation":"DELETE /orgs/reits/actions/runners/{runner_id}","authority":"control credential reference"},{"boundary":"worker-agent","operation":"DestroyRunnerState","authority":"root-owned unix socket"}],"stateMachine":[{"from":"NONE","operation":"registerEphemeral","to":"REGISTERED","guard":"worker is CLOUD_BOUNDARY_CLOSED and both agent/API attest exact ephemeral runner"},{"from":"NONE","operation":"registration proof failure","to":"NO_HANDLE","guard":"DELETE 204/404 plus local destruction is attempted before returning"},{"from":"REGISTERED","operation":"verifyAssignment","to":"VERIFYING_ASSIGNMENT","guard":"exact job and maxJobs=1"},{"from":"VERIFYING_ASSIGNMENT","operation":"job + seal proof","to":"ASSIGNMENT_SEALED","guard":"runner_id/name match and reusable file is absent"},{"from":"VERIFYING_ASSIGNMENT","operation":"proof failure","to":"FAILED_NEEDS_DELETE","guard":"untrusted execution remains denied"},{"from":"REGISTERED","operation":"deleteRunner","to":"DELETING","guard":"pre-assignment compensation"},{"from":"ASSIGNMENT_SEALED","operation":"deleteRunner","to":"DELETING","guard":"normal retirement"},{"from":"FAILED_NEEDS_DELETE","operation":"deleteRunner","to":"DELETING","guard":"failure compensation or retry"},{"from":"DELETING","operation":"204/404 + local destruction","to":"DELETED","guard":"both control-plane and worker-local authority are terminal"},{"from":"DELETED","operation":"deleteRunner","to":"DELETED","guard":"side-effect-free idempotent retry"}],"invariants":["registration occurs only after the EC2 profile is detached, IMDS is disabled and reboot readback passes","the 30-second registration-token handle is issued after cloud-boundary closure, never across launch or reboot","registration secret is passed as the same mutable Buffer and is never copied, serialized, hashed or retained","organization, repository, job, plan, worker, labels and maxJobs are exact rather than caller-selected","runner registration must be ephemeral and independently re-read through the organization-scoped Gitea API","public runner capability excludes control credentials, registration bytes and reusable runner credentials","assignment requires Gitea job status in_progress with exact runner_id, runner_name and labels","Gitea assignment proof and root-owned worker-agent credential proof are distinct and both mandatory","the reusable .runner file is absent before untrusted code while one exact-job lease remains in root daemon memory","reits-job cannot read the runner credential file, agent socket or assignment lease","a second assignment or wrong job is permanently denied","runner deletion accepts only Gitea 204 or already-absent 404 as control-plane terminal","retirement additionally destroys credential files, the in-memory lease and worker-local runner state","registration failures after runner creation attempt cleanup before any capability can escape","failed assignment or deletion stays non-admissible and requires retry or worker termination","no test-driver call counts as a Gitea read, write, live runner or runtime assignment"],"verification":{"status":"PASS_TEST_DRIVER_ONLY","fixtures":34,"allowedTransitions":8,"deniedTransitions":26,"adapterOperations":3,"modeledCalls":6,"internalRegistrationCompensations":3,"idempotentTerminalCases":2,"secretExposureCount":0,"externalCallsExecuted":0},"failureClasses":[{"code":"RF_GITEA_CONFIG|DRIVER|SCOPE|LABELS|WORKER|HANDLE","phase":"PRE_MUTATION","action":"deny without registration"},{"code":"RF_GITEA_REGISTRATION_*","phase":"REGISTRATION","action":"delete any identifiable unemitted runner, destroy local state and terminate worker"},{"code":"RF_GITEA_ASSIGNMENT_*","phase":"ASSIGNMENT","action":"deny job, delete runner and terminate worker"},{"code":"RF_GITEA_CREDENTIAL_SEAL_*","phase":"CREDENTIAL_BOUNDARY","action":"deny untrusted code, delete runner and terminate worker"},{"code":"RF_GITEA_DELETE_*|RF_GITEA_LOCAL_RETIREMENT_PROOF","phase":"RETIREMENT","action":"retry 204/404 reconciliation; freeze capacity if terminal proof remains missing"}],"productionPrerequisites":["least-privilege Gitea credential reference restricted to reits organization runner read/delete and admitted repository job read","root-owned worker-agent binary and unix socket with an authenticated controller channel","runner version and labels pinned in the immutable AMI, with --ephemeral enforced","tmpfs credential path and filesystem/UID denial test proving reits-job cannot read root authority","bounded API retries, delete reconciliation journal and orphan-runner alarm","registration/assignment/retirement runtime receipts joined to plan, worker, runner and job identities","security owner, Gitea owner and runtime owner approval"],"officialReferences":{"liveOpenApi":"https://gitea.reits.tech/swagger.v1.json","openApiVersion":"1.25.4","ephemeralRunners":"https://docs.gitea.com/usage/actions/act-runner#ephemeral-runners"},"fixtureRegistry":{"schemaVersion":"developer.reits.tech/runner-factory-gitea-control-plane-fixtures/v1","fixedTime":"2026-07-20T17:55:00.000Z","cases":[{"id":"RFGC-01","expected":"ALLOW","reason":"EXACT_REQUESTS","scenario":"org runner GET, repository job GET and org runner DELETE remain exactly scoped"},{"id":"RFGC-02","expected":"ALLOW","reason":"REGISTERED","scenario":"cloud-closed worker and mutable token produce an attested ephemeral runner"},{"id":"RFGC-03","expected":"ALLOW","reason":"OPAQUE_CAPABILITY","scenario":"serialized handle contains proof but no mutable authority"},{"id":"RFGC-04","expected":"ALLOW","reason":"ASSIGNMENT_SEALED","scenario":"exact in-progress job and root-agent seal produce a one-job memory lease"},{"id":"RFGC-05","expected":"ALLOW","reason":"DELETE_204","scenario":"present runner and local authority both become terminal"},{"id":"RFGC-06","expected":"ALLOW","reason":"DELETE_404","scenario":"already-absent Gitea runner still requires local destruction"},{"id":"RFGC-07","expected":"ALLOW","reason":"PRE_ASSIGNMENT_COMPENSATION","scenario":"registered runner can retire before assignment"},{"id":"RFGC-08","expected":"ALLOW","reason":"IDEMPOTENT_DELETE","scenario":"retry after terminal proof performs no further calls"},{"id":"RFGC-09","expected":"DENY","reason":"RF_GITEA_CONFIG","scenario":"base URL contains a path"},{"id":"RFGC-10","expected":"DENY","reason":"RF_GITEA_DRIVER","scenario":"driver omits required operations"},{"id":"RFGC-11","expected":"DENY","reason":"RF_GITEA_SCOPE","scenario":"caller requests another organization"},{"id":"RFGC-12","expected":"DENY","reason":"RF_GITEA_SCOPE","scenario":"repository owner is outside reits"},{"id":"RFGC-13","expected":"DENY","reason":"RF_GITEA_REPLAY","scenario":"the same plan, worker, repository and job registration scope is reused"},{"id":"RFGC-14","expected":"DENY","reason":"RF_GITEA_SECRET","scenario":"registration token bytes are empty"},{"id":"RFGC-15","expected":"DENY","reason":"RF_GITEA_LABELS","scenario":"runner requests an unapproved label"},{"id":"RFGC-16","expected":"DENY","reason":"RF_GITEA_WORKER","scenario":"registration is attempted before cloud-boundary closure"},{"id":"RFGC-17","expected":"DENY","reason":"RF_GITEA_REGISTRATION_UNAVAILABLE","scenario":"worker-agent registration is unavailable"},{"id":"RFGC-18","expected":"DENY","reason":"RF_GITEA_REGISTRATION_COMPENSATION","scenario":"agent returns an unknown runner ID so cleanup cannot prove the actual created runner absent"},{"id":"RFGC-19","expected":"DENY","reason":"RF_GITEA_REGISTRATION_READ","scenario":"org runner read returns a mismatched runner ID and internal cleanup passes"},{"id":"RFGC-20","expected":"DENY","reason":"RF_GITEA_REGISTRATION_READ","scenario":"Gitea runner is not ephemeral and internal cleanup passes"},{"id":"RFGC-21","expected":"DENY","reason":"RF_GITEA_REGISTRATION_READ","scenario":"Gitea runner labels drift and internal cleanup passes"},{"id":"RFGC-22","expected":"DENY","reason":"RF_GITEA_ASSIGNMENT_SCOPE","scenario":"assignment job differs from admitted job"},{"id":"RFGC-23","expected":"DENY","reason":"RF_GITEA_ASSIGNMENT_SCOPE","scenario":"assignment permits more than one job"},{"id":"RFGC-24","expected":"DENY","reason":"RF_GITEA_ASSIGNMENT_UNAVAILABLE","scenario":"repository job read is unavailable"},{"id":"RFGC-25","expected":"DENY","reason":"RF_GITEA_ASSIGNMENT_PROOF","scenario":"job is assigned to another runner"},{"id":"RFGC-26","expected":"DENY","reason":"RF_GITEA_ASSIGNMENT_PROOF","scenario":"job has not entered in_progress"},{"id":"RFGC-27","expected":"DENY","reason":"RF_GITEA_ASSIGNMENT_PROOF","scenario":"job labels differ from runner labels"},{"id":"RFGC-28","expected":"DENY","reason":"RF_GITEA_CREDENTIAL_SEAL_UNAVAILABLE","scenario":"root-owned credential seal is unavailable"},{"id":"RFGC-29","expected":"DENY","reason":"RF_GITEA_CREDENTIAL_SEAL_PROOF","scenario":"reusable credential file remains present"},{"id":"RFGC-30","expected":"DENY","reason":"RF_GITEA_ASSIGNMENT_REPLAY","scenario":"runner receives a second assignment"},{"id":"RFGC-31","expected":"DENY","reason":"RF_GITEA_DELETE_PROOF","scenario":"Gitea delete returns a non-terminal status"},{"id":"RFGC-32","expected":"DENY","reason":"RF_GITEA_DELETE_UNAVAILABLE","scenario":"Gitea delete is unavailable"},{"id":"RFGC-33","expected":"DENY","reason":"RF_GITEA_LOCAL_RETIREMENT_PROOF","scenario":"worker-agent local state remains"},{"id":"RFGC-34","expected":"DENY","reason":"RF_GITEA_HANDLE","scenario":"caller forges the opaque capability"}]},"discovery":{"lifecycle":"/api/runner-factory","controller":"/api/runner-factory/controller","workbench":"/release-foundation#gitea-control-plane","schema":"/schemas/runner-factory-gitea-control-plane.v1.schema.json"}}