Stage the CI gate from non-required to required
A required check with a confusing red X loses contributors. Platform may want the gate required on day one. Maintainers who live in contributor Slack want proof it will not punish ordinary PRs. Stage with real traffic before branch protection blocks merges.
Run one week as a non-required job
Evaluate real intents and write audit rows. Do not block merges on the result yet. The step can still fail on deny inside the job; staging lives at the branch-protection layer, not inside @limetry/ci.
The action always records the decision. Whether GitHub treats the job as blocking is a separate, reversible choice.
import { evaluateCiPrivilege } from "@limetry/ci"
const result = await evaluateCiPrivilege({
apiKey: process.env.LIMETRY_API_KEY!,
baseUrl: process.env.LIMETRY_BASE_URL,
policyId: process.env.LIMETRY_CI_POLICY_ID!,
agentId: "github_actions",
actionType: "deploy",
repository: process.env.GITHUB_REPOSITORY!,
sha: process.env.GITHUB_SHA!,
eventName: process.env.GITHUB_EVENT_NAME!,
ref: process.env.GITHUB_REF,
})
process.stdout.write(JSON.stringify({
action_type: result.intent.action_type,
trust: result.trust,
decision: result.evaluation.decision,
reasons: result.evaluation.reasons ?? [],
decision_id: result.evaluation.decision_id,
}, null, 2))
Review audit daily for two failure modes: trusted main runs denied, and untrusted PR runs allowed into deploy. Fix contributor-facing annotations before the check becomes required.
Verify classifications before requiring the check
Example after seven days (184 CI evaluations):
ci_privilege on pull_request: 91 allow
deploy on pull_request: 91 deny
deploy on push to main: 2 approval_required
false classifications: 0
median evaluate latency: 142 ms
highest evaluate latency: 611 ms
Update failure text before requiring the check. After evaluate, require_trusted fails closed on untrusted events with a named event and resource:
Refusing privileged CI for untrusted event pull_request on acme/api@f3a91c2
Audit still carries the policy deny, decision_id, receipt digest, reasons, and expiry.
Make the check required
After staging evidence is clean, require the check. Cost: one extra evaluate call per sensitive job. Return: audit across protected workflows and a check GitHub will block on. Environment rules stay. Limetry remains the first question in the job: should this action type run from this event at this SHA?
Origin: Evaluate before CI loads credentials. Incident context: Deny deploy on a Copilot PR burst before production credentials.
