coderifts 6.0.2 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +75 -0
- package/bin/coderifts.js +60 -0
- package/dist/cli.js +3747 -2161
- package/package.json +3 -2
- package/scripts/assert-guard-major.js +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 7.0.0
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- **`provider-canary`** — proves the gate BLOCKS by attempting a merge that must be refused, creating and cleaning up a real PR; on a non-blocking repo it reverts the probe commit in the same run (`base_reverted`). A successful merge yields `NOT_VERIFIED` and exit 1 — the honest finding, not a bug.
|
|
8
|
+
- **`enforce --check`** gains `--bind-workflow` (writes and reads back the SHA-pinned required-workflow rule), `--require-workflow-binding`, `--head-sha`, and `--env`; runtime read-back covers the rule-suite result, check-run app id, and check-run head_sha. Status vocabulary is VERIFIED / NOT_VERIFIED / UNVERIFIABLE.
|
|
9
|
+
- Thin diff routes (`/api/v1/{grpc,graphql,asyncapi}/diff`) return `422 ANALYSIS_FAILED` on parse errors instead of a generic 500.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `setup-required-check --bind-workflow` and the provider-enforcement evidence envelope (`provider-enforcement-evidence.v2`).
|
|
14
|
+
- Provider adapter shape with GitLab/Bitbucket read-back (plan only; apply is GitHub).
|
|
15
|
+
|
|
16
|
+
### Note
|
|
17
|
+
|
|
18
|
+
- Requires `@coderifts/agent-guard` 13 or 14 (declared `^13.0.0`; the CLI uses base guard APIs, not the ATOMIC profile).
|
|
19
|
+
|
|
20
|
+
## 6.1.0
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **enforce --check now reads GitHub rulesets.** The evaluator existed with zero production call sites: a ruleset-governed repository reported required_check NOT_VERIFIED while its merges were gated. Rulesets are readable where classic protection is not (200 vs 401), so required_check can now reach VERIFIED on an unreadable classic response.
|
|
25
|
+
|
|
3
26
|
## 6.0.2
|
|
4
27
|
|
|
5
28
|
### Fixed
|
package/README.md
CHANGED
|
@@ -421,6 +421,9 @@ failed, **1** on missing repo/key, API error, or any apply failure.
|
|
|
421
421
|
| `--check` | Query GitHub + local workflows (read-only evidence) | `false` |
|
|
422
422
|
| `--env <name>` | With `--check`: GitHub Environment to query | none |
|
|
423
423
|
| `--branch <name>` | With `--check`: branch (default: repo default) | default branch |
|
|
424
|
+
| `--provider <name>` | With `--check`: provider adapter. `github` only; others report UNVERIFIABLE and are never stubbed | `github` |
|
|
425
|
+
| `--head-sha <sha>` | With `--check`: pull-request head commit, so the required-workflow pin can be compared with the bytes being merged | none |
|
|
426
|
+
| `--require-workflow-binding` | With `--check`: also require a sha-pinned required workflow matching the head. **Default OFF** — without it the evidence still gains a `workflow_binding` section and neither the verdict nor the exit code changes | `false` |
|
|
424
427
|
| `--json` | Machine-readable JSON result | `false` |
|
|
425
428
|
|
|
426
429
|
```bash
|
|
@@ -460,6 +463,58 @@ VERIFIED): each layer's status, `reason_code`, the API endpoint consulted,
|
|
|
460
463
|
`queried_at`. Exit **0** when a report was produced (evidence, not a gate).
|
|
461
464
|
GitLab/Bitbucket: no adapter — `UNVERIFIABLE`, never stubbed.
|
|
462
465
|
|
|
466
|
+
### `coderifts provider-canary [repo]`
|
|
467
|
+
|
|
468
|
+
Negative canary: open an ephemeral PR with the contract-gate check failing or
|
|
469
|
+
absent and ask GitHub to merge it. **Blocked is the healthy result.** On a
|
|
470
|
+
repository that does **not** block, the canary leaves a merge+revert commit
|
|
471
|
+
pair on base (that is the finding, stated) — an admin token's revert bypasses
|
|
472
|
+
required checks.
|
|
473
|
+
|
|
474
|
+
| Flag | Description | Default |
|
|
475
|
+
|------|-------------|---------|
|
|
476
|
+
| `[repo]` / `--repo <owner/repo>` | Repository | none (required) |
|
|
477
|
+
| `--confirm` | Required for a real run: this creates a branch and a pull request | none — without it (and without `--dry-run`) the command exits **2** rather than touching the repo |
|
|
478
|
+
| `--dry-run` | Do not touch the provider; report the shape only | `false` |
|
|
479
|
+
| `--json` | Machine-readable evidence document | `false` |
|
|
480
|
+
|
|
481
|
+
Exit **0** only when the provider refused the merge. A merge that **succeeds**
|
|
482
|
+
is the finding: `blocked:false`, status `NOT_VERIFIED`, exit **1**.
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
coderifts provider-canary --repo owner/repo --dry-run
|
|
486
|
+
coderifts provider-canary --repo owner/repo --confirm
|
|
487
|
+
coderifts provider-canary --repo owner/repo --confirm --json
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### `coderifts grant publish`
|
|
491
|
+
|
|
492
|
+
Encodes an **already-signed** execution grant plus the PR head sha into a
|
|
493
|
+
comment marker on stdout, for the 1094 PR-comment delivery slot. **It does not
|
|
494
|
+
mint a grant** (`src/commands/grant-publish.js:4`) — the token must already be a
|
|
495
|
+
signed `cr.exec.v1` or `cr.exec.v2`.
|
|
496
|
+
|
|
497
|
+
| Flag | Description | Default |
|
|
498
|
+
|------|-------------|---------|
|
|
499
|
+
| `--head-sha <sha>` | **Required.** 40-hex PR head sha the grant binds | none |
|
|
500
|
+
| `--grant <token>` | **Required.** `cr.exec.v1` or `cr.exec.v2` token | none |
|
|
501
|
+
| `--after-payload-hash <hash>` | `sha256:…` of the after-payload | empty string |
|
|
502
|
+
|
|
503
|
+
Writes `<!-- coderifts-grant-v2 -->` followed by one JSON line. Pipe it to
|
|
504
|
+
`gh api` or post it as a PR comment. Bad `--head-sha` or a missing `--grant`
|
|
505
|
+
exits **2** with usage.
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
coderifts grant publish --head-sha "$HEAD" --grant "$TOKEN" > /tmp/marker.txt
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
**Reaching the gate today:** the contract-gate Action reads a grant from its
|
|
512
|
+
`execution-grant:` input, not from PR comments — `main()` in the gate does not
|
|
513
|
+
pass `grantComments`, so the comment path is not yet wired end to end. Until it
|
|
514
|
+
is, deliver the token through the `CODERIFTS_EXECUTION_GRANT` repository
|
|
515
|
+
variable, and note that a grant binds one after-payload, so a pinned variable
|
|
516
|
+
covers exactly one diff.
|
|
517
|
+
|
|
463
518
|
### Agent host files (`coderifts agent-setup`)
|
|
464
519
|
|
|
465
520
|
Writes the six CodeRifts agent-host rule files **plus** the Claude Code
|
|
@@ -534,6 +589,11 @@ via `coderifts registry-gate`). The wizard:
|
|
|
534
589
|
existing protection settings
|
|
535
590
|
5. **`--apply`:** runs that PUT with your credentials, then **re-reads** and
|
|
536
591
|
only reports success if the check is required
|
|
592
|
+
6. **`--bind-workflow`:** create/update a repository ruleset `workflows` rule
|
|
593
|
+
pinning `.github/workflows/coderifts.yml` (the STRICT template filename)
|
|
594
|
+
to its current **blob sha** on the target branch (`enforcement: active`,
|
|
595
|
+
`bypass_actors: []`). Dry-run unless combined with `--apply`. Read-back
|
|
596
|
+
uses `github-workflow-pin.js`; reports `APPLIED` only on `VERIFIED`.
|
|
537
597
|
|
|
538
598
|
**Why the App never writes protection:** mutating branch protection needs
|
|
539
599
|
`administration:write` — a trust jump we refuse. Your credentials do the write.
|
|
@@ -542,6 +602,15 @@ via `coderifts registry-gate`). The wizard:
|
|
|
542
602
|
`merge_group` webhook (`checks_requested`) and posts **CodeRifts / contract-gate**
|
|
543
603
|
on the merge group head (same gate as PR heads), so the queue does not stall.
|
|
544
604
|
|
|
605
|
+
| Flag | Description | Default |
|
|
606
|
+
|------|-------------|---------|
|
|
607
|
+
| `--repo <owner/repo>` | Override owner/repo | `git remote origin` |
|
|
608
|
+
| `--branch <name>` | Branch to protect | repo default branch |
|
|
609
|
+
| `--apply` | Apply the protection change | print the `gh` command only |
|
|
610
|
+
| `--bind-workflow` | Create/update a ruleset `workflows` rule pinning `.github/workflows/coderifts.yml` (STRICT template) by blob sha | `false` |
|
|
611
|
+
| `--enforce-admins` | Set `enforce_admins:true` on create | `false` — admins can bypass; the gate reports `admin_bypass_open` |
|
|
612
|
+
| `--json` | Machine-readable JSON result | `false` |
|
|
613
|
+
|
|
545
614
|
```bash
|
|
546
615
|
# Observe + print command (safe default)
|
|
547
616
|
coderifts setup-required-check
|
|
@@ -549,6 +618,12 @@ coderifts setup-required-check
|
|
|
549
618
|
# Apply + re-verify
|
|
550
619
|
coderifts setup-required-check --apply
|
|
551
620
|
|
|
621
|
+
# Pin the STRICT workflow by blob sha (ruleset `workflows` rule)
|
|
622
|
+
coderifts setup-required-check --bind-workflow --apply
|
|
623
|
+
|
|
624
|
+
# Admins cannot bypass either (opt-in; NOT the default)
|
|
625
|
+
coderifts setup-required-check --apply --enforce-admins
|
|
626
|
+
|
|
552
627
|
# One-liner for CI docs
|
|
553
628
|
coderifts setup-required-check --branch main
|
|
554
629
|
```
|
package/bin/coderifts.js
CHANGED
|
@@ -85,6 +85,60 @@ program
|
|
|
85
85
|
process.exit(code);
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
// ── provider canary (1105 negative enforcement proof) ──
|
|
89
|
+
//
|
|
90
|
+
// NOT read-only, and deliberately not hidden behind --apply: it creates a branch and a pull request
|
|
91
|
+
// on the named repository and asks the provider to merge them. --dry-run is the safe default the
|
|
92
|
+
// tests drive; a real run needs --confirm so nobody discovers this command by tab-completion.
|
|
93
|
+
program
|
|
94
|
+
.command('provider-canary [repo]')
|
|
95
|
+
.description('Prove the gate BLOCKS by attempting a merge that must be refused (creates + cleans up a real PR). On a non-blocking repo the canary leaves a merge+revert commit pair on base (the finding); an admin token\'s revert bypasses required checks.')
|
|
96
|
+
.option('--repo <owner/repo>', 'Repository (owner/repo); also accepted as a positional argument')
|
|
97
|
+
.option('--dry-run', 'Do not touch the provider; report the shape only', false)
|
|
98
|
+
.option('--confirm', 'Required for a real run: this creates a branch and a pull request')
|
|
99
|
+
.option('--json', 'Machine-readable evidence document')
|
|
100
|
+
.action(async (repoPositional, options) => {
|
|
101
|
+
const { runProviderCanary } = require('../src/commands/provider-canary');
|
|
102
|
+
if (!options.dryRun && !options.confirm) {
|
|
103
|
+
console.error(
|
|
104
|
+
'provider-canary creates a real branch and pull request on the target repository and then '
|
|
105
|
+
+ 'asks GitHub to merge it. Re-run with --confirm, or with --dry-run to see the shape.',
|
|
106
|
+
);
|
|
107
|
+
process.exit(2);
|
|
108
|
+
}
|
|
109
|
+
const result = await runProviderCanary(
|
|
110
|
+
{ ...options, repo: options.repo || repoPositional },
|
|
111
|
+
{},
|
|
112
|
+
);
|
|
113
|
+
// The command prints (JSON or human) exactly once, after cleanup — see report() there.
|
|
114
|
+
process.exit(result.exitCode);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ── grant publish (1094 PR-comment delivery) ──
|
|
118
|
+
program
|
|
119
|
+
.command('grant')
|
|
120
|
+
.description('Execution-grant helpers')
|
|
121
|
+
.command('publish')
|
|
122
|
+
.description('Encode a signed grant + head_sha as a PR-comment marker (stdout)')
|
|
123
|
+
.requiredOption('--head-sha <sha>', '40-hex PR head SHA the grant binds')
|
|
124
|
+
.requiredOption('--grant <token>', 'cr.exec.v1 or cr.exec.v2 token')
|
|
125
|
+
.option('--after-payload-hash <hash>', 'sha256:… of the after-payload')
|
|
126
|
+
.action((options) => {
|
|
127
|
+
const { runGrantPublish } = require('../src/commands/grant-publish');
|
|
128
|
+
const result = runGrantPublish({
|
|
129
|
+
headSha: options.headSha,
|
|
130
|
+
grant: options.grant,
|
|
131
|
+
afterPayloadHash: options.afterPayloadHash,
|
|
132
|
+
});
|
|
133
|
+
if (!result.ok) {
|
|
134
|
+
console.error(result.error);
|
|
135
|
+
if (result.usage) console.error(result.usage);
|
|
136
|
+
process.exitCode = result.exitCode;
|
|
137
|
+
process.exit(result.exitCode);
|
|
138
|
+
}
|
|
139
|
+
process.stdout.write(result.text + '\n');
|
|
140
|
+
});
|
|
141
|
+
|
|
88
142
|
// ── init command ──
|
|
89
143
|
// `init [template]` writes a policy YAML. `init --agents` is a different path:
|
|
90
144
|
// it wires MCP config + agent rules + host hook + the CI gate workflow.
|
|
@@ -153,6 +207,7 @@ program
|
|
|
153
207
|
.option('--branch <name>', 'Branch to protect (default: repo default branch)')
|
|
154
208
|
.option('--repo <owner/repo>', 'Override owner/repo (default: git remote origin)')
|
|
155
209
|
.option('--apply', 'Apply the protection change (default: print the exact gh command only)')
|
|
210
|
+
.option('--bind-workflow', 'Create/update a ruleset workflows rule pinning .github/workflows/coderifts.yml (STRICT template) by blob sha; dry-run unless --apply')
|
|
156
211
|
.option('--enforce-admins', 'Set enforce_admins:true on create (default: false — admins can bypass; gate reports admin_bypass_open)')
|
|
157
212
|
.option('--json', 'Machine-readable JSON result')
|
|
158
213
|
.action(async (options) => {
|
|
@@ -193,6 +248,11 @@ program
|
|
|
193
248
|
.option('--env <name>', 'With --check: GitHub Environment name to query for protection rules')
|
|
194
249
|
.option('--branch <name>', 'With --check: branch to query (default: repository default branch)')
|
|
195
250
|
.option('--provider <name>', 'With --check: provider adapter (github only; others UNVERIFIABLE, never stubbed)', 'github')
|
|
251
|
+
// 1102 — DEFAULT OFF ON PURPOSE. With the flag absent the evidence gains a workflow_binding
|
|
252
|
+
// section and NOTHING about the verdict or the exit code changes. Turning it on is a decision
|
|
253
|
+
// about how strong a claim this repository is willing to make, not a bug fix, so it is Peter's.
|
|
254
|
+
.option('--require-workflow-binding', 'With --check: also require a sha-pinned required workflow matching the head (default: off)')
|
|
255
|
+
.option('--head-sha <sha>', 'With --check: pull-request head commit, so the workflow pin can be compared with the bytes being merged')
|
|
196
256
|
.option('--json', 'Machine-readable JSON result')
|
|
197
257
|
.action(async (repoPositional, options) => {
|
|
198
258
|
const { runEnforce } = require('../src/commands/enforce');
|