{"schemaVersion":"developer.reits.tech/runner-capacity/v1","status":"ACTIVE_BLOCKED","observedAt":"2026-07-21T07:56:54Z","current":{"linux":{"registered":1,"online":1,"scope":"repository","repository":"reits/im-core","eligibleRepositories":1},"macos":{"registered":2,"online":0,"scope":"unavailable","eligibleRepositories":0},"organization":{"registered":0,"online":0,"successfulGates":1,"queuedGates":17},"productionHostEligible":false,"productionHostGuard":{"status":"BOUND","path":"/etc/reits-production-host","runnerServiceActive":false,"observedAt":"2026-07-21T07:56:54Z"},"reason":"The only accessible EC2 hosts public web, Gitea, IM, business services, databases and logging; CI workloads must not share this failure and trust domain."},"target":{"linuxOrganizationRunners":2,"macosOrganizationRunners":1,"concurrencyPerRunner":1,"ephemeralWorkspace":true,"singleUseRunnerCredential":true,"jobIsolation":"ephemeral-vm-or-rootless-dind","dedicatedCompute":true,"productionNetworkAccess":false,"dockerSocketMounted":false},"isolation":["Dedicated CI compute account or VM; no production service is co-located.","Untrusted pull-request jobs cannot access home directories, cloud credentials, Docker sockets or production subnets.","The organization registration secret exists only during offline bootstrap, is never committed/logged and is reset before any daemon starts.","CPU, memory, process, disk and job duration limits are enforced; workspaces are destroyed after every job.","The job UID can reach only loopback; outbound CONNECT requests pass through a root-managed proxy allowlist that denies private destinations and direct sockets."],"registration":{"scope":"organization","organization":"reits","tokenEndpoint":"/api/v1/orgs/reits/actions/runners/registration-token","linuxLabels":["ubuntu-latest","ubuntu-24.04"],"macosLabels":["macos-latest","self-hosted","macOS"],"tokenStorage":"GITEA_RUNNER_REGISTRATION_TOKEN_FILE","tokenValueRecorded":false},"provisioning":{"status":"REVISION_REQUIRED","liveStackStatus":"NOT_DEPLOYED","costApprovalRequired":true,"template":"ops/gitea-runner/cloudformation.yaml","deployCommand":"ops/gitea-runner/deploy.sh","preflightCommand":"npm run runner-foundation:verify","validation":{"staticPolicy":"PASS","cfnLint":"PASS","awsValidateTemplate":"BLOCKED_IAM","awsPrincipal":"iam-user/cc","observedAt":"2026-07-20T11:40:44Z"},"topology":{"vpc":"new-ci-only-vpc","availabilityZones":2,"linuxInstances":2,"instanceTypeDefault":"t3.large","inboundRules":0,"outboundPolicy":"job UID may open only TCP 127.0.0.1:3128; root-managed CONNECT broker/bootstrap retain security-group HTTPS","productionVpcRoute":false},"cleanup":{"status":"HOOK_READY_UNTRUSTED_RECEIPT","runnerVersion":"2.0.0","postTaskScript":"ops/gitea-runner/post-task-cleanup.sh","timeout":"1m","roots":["/var/lib/reits-runner/work","/var/lib/reits-runner/tmp"],"builtInCleanupPrecedesHook":true,"trustedReceipt":false,"reason":"Gitea Runner 2.0.0 invokes the root-owned hook after built-in cleanup, but the hook still runs as the reusable daemon/job UID and cannot issue a trusted isolation receipt."},"credentialBoundary":{"status":"BLOCKED_HOST_EXECUTOR_SHARED_UID","observedAt":"2026-07-20T12:08:15Z","giteaVersion":"1.25.4","templateRunnerVersion":"2.0.0","executionMode":"host","daemonUser":"reits-runner","jobUser":"reits-runner","credentialPath":"/var/lib/reits-runner/.runner","jobCanReadRunnerCredential":true,"credentialRevokedBeforeJob":false,"runnerReusableAcrossJobs":true,"deploymentPermitted":false,"blockCode":"RUNNER_CREDENTIAL_SHARED_UID","minimumEphemeralVersion":"0.2.12","safeTarget":"single-use ephemeral VM factory with the rootless DinD lifecycle contract at /api/runner-factory","officialReference":"https://docs.gitea.com/1.24/usage/actions/act-runner#ephemeral-runners","acceptance":["The job cannot read or reuse the daemon credential file.","The runner credential is revoked before untrusted code starts.","The compute or rootless container boundary is replaced after each job.","Cleanup and replacement emit an operator-trusted receipt."]},"egress":{"status":"TEMPLATE_READY","enforcement":"job-uid-proxy-endpoint-only","proxy":"http://127.0.0.1:3128","permittedJobSockets":["tcp://127.0.0.1:3128"],"directJobNetwork":false,"loopbackDnsDenied":true,"otherLoopbackDenied":true,"privateDestinationsDenied":true,"allowlistSource":"ops/gitea-runner/egress-allowlist.txt","allowedDomains":16,"fixtureCases":13,"domainGroups":[{"id":"control","label":"Gitea control","domains":["gitea.reits.tech","dl.gitea.com"]},{"id":"node","label":"Node packages","domains":["nodejs.org","registry.npmjs.org"]},{"id":"go","label":"Go modules","domains":["proxy.golang.org","sum.golang.org","storage.googleapis.com"]},{"id":"source","label":"Source fixtures","domains":["github.com","api.github.com","objects.githubusercontent.com","raw.githubusercontent.com"]},{"id":"rust","label":"Rust crates","domains":["crates.io","static.crates.io","index.crates.io"]},{"id":"python","label":"Python packages","domains":["pypi.org","files.pythonhosted.org"]}],"credentialsLogged":false,"validation":["Squid binds only to loopback and denies non-CONNECT, non-443, private, link-local and unlisted destinations.","A root-owned nftables output chain permits only TCP 127.0.0.1:3128 for the reits-runner UID and rejects every other IPv4, IPv6, UDP and loopback socket.","The runner service exports uppercase and lowercase proxy variables and requires the egress guard service.","The allowlist and proxy configuration are immutable root-owned inputs and contain no credential values.","Thirteen deterministic cases cover allowed paths plus direct, loopback DNS, local-service, IPv6 loopback, suffix, literal-IP, private, metadata, non-443 and unlisted denial."],"residualRisks":["The template is not deployed, so runtime enforcement and recovery receipts do not yet exist.","CONNECT authority filtering still requires an adversarial shared-CDN/SNI drill before acceptance.","Allowlisted package and source domains remain possible exfiltration channels; untrusted pull requests must receive no reusable secret.","Changing a package domain requires an owner-reviewed allowlist revision and a replacement rollout."]},"bootstrapBoundary":["Runner registrations remain offline while the bootstrap IAM profile and IMDS are present.","The reusable Gitea registration token is rotated and its SSM SecureString is deleted before activation.","Both instance profiles are detached and IMDS is disabled before the first runner daemon starts.","Any replacement node remains fail-closed until the explicit finalization sequence is repeated."],"phases":[{"id":"R1","label":"Policy + template","status":"COMPLETE"},{"id":"R2","label":"Local cfn-lint","status":"COMPLETE"},{"id":"R3","label":"Egress guard static","status":"COMPLETE"},{"id":"R4","label":"Credential boundary","status":"BLOCKED"},{"id":"R5","label":"AWS API validation","status":"BLOCKED_IAM"},{"id":"R6","label":"Cost-approved provision","status":"APPROVAL_REQUIRED"},{"id":"R7","label":"18-gate isolation drill","status":"BLOCKED"},{"id":"R8","label":"Mac native lane","status":"BLOCKED"}]},"acceptance":["Both Linux organization runners are online and visible to at least two repositories.","A fixture pull request completes the evidence gate in every one of the 18 core repositories.","A malicious fixture cannot read host, cloud, Gitea admin or production-network material.","Mac Swift package and iOS policy lanes execute on the dedicated Mac runner.","Runner loss, queue depth and saturation are observable without treating queued as passed."],"discovery":{"workbench":"/release-foundation","schema":"/schemas/runner-capacity.v1.schema.json","auditSchema":"/schemas/runner-live-audit.v1.schema.json","audit":"/api/runner-audit","evidence":"/api/runner-capacity/evidence","evidenceSchema":"/schemas/runner-capacity-evidence.v1.schema.json","controllerReadinessEvidence":"/api/runner-controller/readiness-evidence","factorySchema":"/schemas/runner-factory.v1.schema.json","factory":"/api/runner-factory","releaseUnits":"/api/release-units"}}