{"schemaVersion":"developer.reits.tech/runner-capacity/v1","status":"ACTIVE_BLOCKED","observedAt":"2026-07-29T04:47:01Z","current":{"linux":{"registered":1,"online":1,"scope":"repository","repository":"reits/im-core","eligibleRepositories":0},"macos":{"registered":8,"online":6,"scope":"repository-reusable-mixed-labels","eligibleRepositories":0},"organization":{"registered":0,"online":0,"successfulGates":0,"queuedGates":0},"productionHostEligible":false,"productionHostGuard":{"status":"BOUND","path":"/etc/reits-production-host","runnerServiceActive":false,"observedAt":"2026-07-29T04:47:01Z"},"reason":"9 台 Runner 中 7 台在线，但全部是仓库级且可复用；组织级、ephemeral、独立隔离和签名回执均为零。"},"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 remains in SSM for replacement bootstrap, is readable only by the temporary bootstrap role and is never mounted into a task.","CPU, memory, process and job duration limits are enforced; the ephemeral runner exits after one job and the entire VM is powered off for ASG replacement.","Job containers can reach only the root-managed proxy on the dedicated Docker bridge; forwarding and every other host socket are denied."],"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":"AWS_SSM_SECURESTRING_BOOTSTRAP_ONLY","tokenValueRecorded":false},"provisioning":{"status":"COST_AND_CLOUD_APPROVAL_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_IDENTITY_ABSENT","awsPrincipal":null,"priorAwsPrincipal":"iam-user/cc","priorObservationFreshness":"STALE_SUPERSEDED","identityContract":"ops/aws-validation-identity/cloudformation.yaml","identityVerifier":"ops/aws-validation-identity/validate-template.sh","observedAt":"2026-07-24T07:38:32Z"},"costApproval":{"status":"REPOSITORY_IMPLEMENTED_DUAL_APPROVAL_REQUIRED","contract":"ops/runner-cost-approval/request.json","verifier":"ops/runner-cost-approval/verify-receipt.mjs","templateSha256":"62d847f115feab4d01dd6d58fdb211a3d1b94c8ed5e3580de5c5b1463116cadb","fixedMonthlyBaseUsd":176.836,"proposedMonthlyAuthorizationCeilingUsd":250,"requiredRoles":["PRODUCT_OWNER","FINOPS"],"observedSignatures":0,"validReceiptsObserved":0,"leaseMaximumDays":31,"leaseExpiryAction":"SET_ASG_MIN_DESIRED_MAX_TO_ZERO","deploymentAdmitted":false},"topology":{"vpc":"new-ci-only-vpc","availabilityZones":2,"linuxInstances":2,"instanceTypeDefault":"t3.large","inboundRules":0,"outboundPolicy":"task containers may open only TCP 172.30.0.1:3128; root-managed CONNECT broker/bootstrap retain security-group HTTPS","productionVpcRoute":false},"cleanup":{"status":"EPHEMERAL_VM_RETIREMENT_REPOSITORY_BOUND_LIVE_RECEIPT_REQUIRED","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":"Repository code now wipes task roots and runner credential, powers off the single-job VM and relies on ASG replacement; a live retirement/replacement receipt is still required."},"credentialBoundary":{"status":"REPOSITORY_BOUND_EPHEMERAL_VM_LIVE_QUALIFICATION_REQUIRED","observedAt":"2026-07-24T16:10:00Z","giteaVersion":"1.25.4","templateRunnerVersion":"2.0.0","executionMode":"docker-on-disposable-vm","daemonUser":"reits-runner","jobUser":"container-isolated","credentialPath":"/var/lib/reits-runner/.runner","jobCanReadRunnerCredential":false,"credentialRevokedBeforeJob":true,"runnerReusableAcrossJobs":false,"deploymentPermitted":true,"blockCode":"LIVE_QUALIFICATION_AND_OWNER_AUTHORITY_REQUIRED","minimumEphemeralVersion":"0.2.12","safeTarget":"single-use ephemeral VM with Docker task containers, no task socket mount, pre-start AWS authority quarantine and whole-VM retirement","officialReference":"https://docs.gitea.com/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":"CONTAINER_FIREBREAK_REPOSITORY_BOUND","enforcement":"container-bridge-proxy-endpoint-only","proxy":"http://172.30.0.1:3128","permittedJobSockets":["tcp://172.30.0.1:3128"],"directJobNetwork":false,"loopbackDnsDenied":true,"otherLoopbackDenied":true,"privateDestinationsDenied":true,"allowlistSource":"ops/gitea-runner/egress-allowlist.txt","allowedDomains":21,"fixtureCases":14,"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"]},{"id":"docker","label":"Pinned Docker image pull","domains":["auth.docker.io","registry-1.docker.io","production.cloudflare.docker.com","production.cloudfront.docker.com","docker.io"]}],"credentialsLogged":false,"validation":["Squid binds only to loopback and denies non-CONNECT, non-443, private, link-local and unlisted destinations.","Root-owned nftables input/forward chains permit only TCP 172.30.0.1:3128 from reits-ci0, permit same-bridge service traffic and reject every other forwarded or host-bound task socket; task DNS is pinned to the container's empty loopback so Docker's embedded resolver cannot become an exfiltration relay.","The runner config injects uppercase and lowercase task proxy variables; both the runner and Docker daemon use loopback Squid, while task containers use the bridge endpoint and require the egress guard service.","The allowlist and proxy configuration are immutable root-owned inputs and contain no credential values.","Fourteen deterministic cases cover Gitea, package and pinned Docker image pulls plus direct, Docker embedded 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":["Each runner is registered with --ephemeral while its daemon remains offline.","The reusable organization registration token stays encrypted in SSM for ASG replacement and never crosses into a task container.","Each node disables IMDS and detaches its instance profile before the first runner daemon starts.","The runner credential is revoked before untrusted code, the daemon exits after one job, and the VM wipes local state then powers off for replacement."],"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":"REPOSITORY_COMPLETE_LIVE_QUALIFICATION_REQUIRED"},{"id":"R5","label":"AWS API validation","status":"REPOSITORY_READY_IDENTITY_ABSENT"},{"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","credentialBoundary":"/api/runner-credential-boundary","credentialBoundarySchema":"/schemas/runner-credential-boundary.v1.schema.json","controllerReadinessEvidence":"/api/runner-controller/readiness-evidence","factorySchema":"/schemas/runner-factory.v1.schema.json","factory":"/api/runner-factory","releaseUnits":"/api/release-units"}}