code-foundry 1.48.7 → 1.50.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.
@@ -220,14 +220,14 @@ Keep pull requests focused and reviewable. Include screenshots or recordings for
220
220
 
221
221
  ## Workflow and check behavior
222
222
 
223
- | Event | Expected automation |
224
- | -------------------------------------------------- | ------------------------------------------------------------------------------------- |
225
- | Draft pull request targeting `main` | No runner-heavy validation; run local checks before requesting review |
226
- | Ready pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |
227
- | Exact Release Please pull request targeting `main` | Full validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |
228
- | Scheduled or manual validation | Full audit tier |
229
- | Push to a working branch | Draft PR workflow |
230
- | Push to `main` | Release workflow; CodeQL skips release-only merges (audit covers drift) |
223
+ | Event | Expected automation |
224
+ | ---------------------------------------- | ---------------------------------------------------------------------------------------------------- |
225
+ | Draft pull request targeting `main` | No runner-heavy validation; run local checks before requesting review |
226
+ | Ready pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |
227
+ | Exact Release Please PR targeting `main` | Release diff, configured CodeQL, build/package check, and either a verified receipt or full CI/tests |
228
+ | Scheduled or manual validation | Full audit tier |
229
+ | Push to a working branch | Draft PR workflow |
230
+ | Push to `main` | Release workflow; CodeQL skips release-only merges (audit covers drift) |
231
231
 
232
232
  Draft pull requests do not start validation unless `draft_protection: false` is configured. The lightweight Draft Guard converts ordinary pull requests opened or reopened while ready back to draft; it never checks out pull-request code and it excludes Release Please version heads, whose release workflow owns their state. Marking a pull request ready for review starts the applicable validation tier, and each new commit on a ready pull request reruns that tier for the current head. Draft updates allocate no validation runner while protection is enabled. Converting a pull request to draft runs only the lightweight cancellation control.
233
233
 
@@ -7,6 +7,16 @@
7
7
  "description": "Explicit JavaScript formatter. Omit to preserve repository scripts and the Oxfmt fallback.",
8
8
  "type": "string",
9
9
  "enum": ["oxfmt", "prettier", "bun"]
10
+ },
11
+ "release_qualification_receipts": {
12
+ "description": "Opt in to seven-day exact-tree qualification receipts for Release Please validation.",
13
+ "type": "string",
14
+ "enum": ["true", "false"]
15
+ },
16
+ "npm_publish_auth": {
17
+ "description": "npm publisher authentication: auto preserves token users and uses OIDC when no publish token is present; oidc forces trusted publishing; token requires NPM_TOKEN.",
18
+ "type": "string",
19
+ "enum": ["auto", "oidc", "token"]
10
20
  }
11
21
  },
12
22
  "additionalProperties": true
@@ -5,6 +5,7 @@ languages: typescript
5
5
  features: all
6
6
  draft_protection: true
7
7
  codeql: auto
8
+ release_qualification_receipts: false
8
9
  codeql_rust_shards: '["all"]'
9
10
  codeql_rust_threads: 1
10
11
  codeql_rust_max_parallel: 1
@@ -15,6 +16,7 @@ runtime_repository: 0xPlayerOne/code-foundry
15
16
  runtime_ref: v1.30.0
16
17
  release_type: node
17
18
  npm_publish: true
19
+ npm_publish_auth: oidc
18
20
  license: agpl-3.0-or-later
19
21
  git_workflow: direct
20
22
  merge_strategy: squash
@@ -23,6 +23,16 @@ on:
23
23
  required: false
24
24
  type: string
25
25
  default: task-result
26
+ release-build-only:
27
+ description: Run only the build lane after an exact successful source qualification receipt.
28
+ required: false
29
+ type: boolean
30
+ default: false
31
+ release-package-check:
32
+ description: Inspect the versioned npm package contents on release pull requests.
33
+ required: false
34
+ type: boolean
35
+ default: false
26
36
  secrets:
27
37
  TURBO_TOKEN:
28
38
  required: false
@@ -55,7 +65,7 @@ concurrency:
55
65
  jobs:
56
66
  format:
57
67
  name: Format
58
- if: vars.CI_BILLING_PAUSED != 'true'
68
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.release-build-only != true
59
69
  runs-on: ${{ inputs.runner }}
60
70
  timeout-minutes: 30
61
71
  steps:
@@ -124,7 +134,7 @@ jobs:
124
134
 
125
135
  lint:
126
136
  name: Lint
127
- if: vars.CI_BILLING_PAUSED != 'true'
137
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.release-build-only != true
128
138
  runs-on: ${{ inputs.runner }}
129
139
  timeout-minutes: 30
130
140
  steps:
@@ -188,7 +198,7 @@ jobs:
188
198
 
189
199
  type-check:
190
200
  name: Type-Check
191
- if: vars.CI_BILLING_PAUSED != 'true'
201
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.release-build-only != true
192
202
  permissions:
193
203
  contents: read
194
204
  issues: read
@@ -279,6 +289,7 @@ jobs:
279
289
  path: .github/.code-foundry
280
290
  sparse-checkout: |
281
291
  .github/actions
292
+ src/commands/qualification-receipt.mjs
282
293
  src/lib
283
294
  src/runtime-core.mjs
284
295
  src/runtime.mjs
@@ -287,6 +298,11 @@ jobs:
287
298
  mkdir -p .github/actions
288
299
  mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
289
300
  cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
301
+ - name: Set up Node.js 24.18.0 for package inspection
302
+ if: inputs.release-package-check == true
303
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
304
+ with:
305
+ node-version: 24.18.0
290
306
  - name: Detect
291
307
  id: applicability
292
308
  env:
@@ -296,8 +312,13 @@ jobs:
296
312
  HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
297
313
  BEFORE_SHA: ${{ github.event.before }}
298
314
  run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run build >> "$GITHUB_OUTPUT"
315
+ - name: Verify versioned package build contract
316
+ if: inputs.release-package-check == true
317
+ env:
318
+ FOUNDRY_BUILD_TASK_APPLICABLE: ${{ steps.applicability.outputs.applicable }}
319
+ run: node "$RUNNER_TEMP/code-foundry/src/commands/qualification-receipt.mjs" package-contract
299
320
  - name: Setup
300
- if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
321
+ if: steps.applicability.outputs.applicable == 'true' && (inputs.release-build-only == true || steps.applicability.outputs.affected != 'false')
301
322
  uses: ./.github/actions/setup
302
323
  with:
303
324
  install: 'true'
@@ -305,8 +326,23 @@ jobs:
305
326
  task: build
306
327
  - name: Build
307
328
  id: execute
308
- if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
329
+ if: steps.applicability.outputs.applicable == 'true' && (inputs.release-build-only == true || steps.applicability.outputs.affected != 'false')
309
330
  run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci build
331
+ - name: Inspect versioned npm package contents
332
+ if: inputs.release-package-check == true && hashFiles('package.json') != ''
333
+ run: |
334
+ npm pack --dry-run --ignore-scripts --json > "$RUNNER_TEMP/foundry-package-inspection.json"
335
+ node --input-type=module -e '
336
+ import { readFileSync } from "node:fs";
337
+ import { join } from "node:path";
338
+ import { pathToFileURL } from "node:url";
339
+
340
+ const runtime = join(process.env.RUNNER_TEMP, "code-foundry", "src/lib/node-package-performance.mjs");
341
+ const { verifyNpmPackPackage } = await import(pathToFileURL(runtime).href);
342
+ const manifest = JSON.parse(readFileSync("package.json", "utf8"));
343
+ const report = JSON.parse(readFileSync(process.argv[1], "utf8"));
344
+ verifyNpmPackPackage(report, manifest);
345
+ ' "$RUNNER_TEMP/foundry-package-inspection.json"
310
346
  - name: Retain task receipt
311
347
  if: >-
312
348
  always() &&
@@ -36,11 +36,11 @@ jobs:
36
36
  exit 1
37
37
  fi
38
38
 
39
- read -r draft head_ref head_sha updated_at < <(
39
+ read -r draft head_ref head_sha updated_at node_id < <(
40
40
  gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER" \
41
- --jq '[.draft, .head.ref, .head.sha, .updated_at] | @tsv'
41
+ --jq '[.draft, .head.ref, .head.sha, .updated_at, .node_id] | @tsv'
42
42
  )
43
- if [ -z "$draft" ] || [ -z "$head_ref" ] || [ -z "$head_sha" ] || [ -z "$updated_at" ]; then
43
+ if [ -z "$draft" ] || [ -z "$head_ref" ] || [ -z "$head_sha" ] || [ -z "$updated_at" ] || [ -z "$node_id" ]; then
44
44
  echo '::error title=Draft guard cannot verify current state::The GitHub API response did not include the required pull-request metadata.'
45
45
  exit 1
46
46
  fi
@@ -70,9 +70,13 @@ jobs:
70
70
  exit 1
71
71
  fi
72
72
 
73
- gh api \
74
- --method PATCH \
75
- "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER" \
76
- -F draft=true \
77
- --silent >/dev/null
73
+ result=$(gh api graphql \
74
+ -f query='mutation($pullRequestId: ID!) { convertPullRequestToDraft(input: {pullRequestId: $pullRequestId}) { pullRequest { id isDraft } } }' \
75
+ -f pullRequestId="$node_id" \
76
+ --jq '.data.convertPullRequestToDraft.pullRequest | [.id, .isDraft] | @tsv')
77
+ read -r returned_id is_draft <<< "$result"
78
+ if [ "$returned_id" != "$node_id" ] || [ "$is_draft" != true ]; then
79
+ echo '::error title=Draft guard conversion failed::GraphQL did not confirm the expected pull request is a draft.'
80
+ exit 1
81
+ fi
78
82
  echo "Converted ordinary pull request #$PR_NUMBER to draft; validation waits for ready_for_review."
@@ -0,0 +1,201 @@
1
+ name: Code Foundry Qualification Receipt
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ phase:
7
+ description: Produce evidence after a full audit or verify it for a release PR.
8
+ required: true
9
+ type: string
10
+ mode:
11
+ description: Validation tier associated with this receipt operation.
12
+ required: true
13
+ type: string
14
+ enabled:
15
+ description: Consumer opt-in for qualification receipt reuse.
16
+ required: false
17
+ type: boolean
18
+ default: false
19
+ codeql-enabled:
20
+ description: Whether the consumer requires CodeQL in its audit and release lanes.
21
+ required: false
22
+ type: boolean
23
+ default: true
24
+ runtime-repository:
25
+ description: Repository containing the Code Foundry runtime.
26
+ required: true
27
+ type: string
28
+ runtime-ref:
29
+ description: Runtime commit, tag, or ref used by source validation.
30
+ required: true
31
+ type: string
32
+ job-results-json:
33
+ description: Normalized component results for the successful full audit.
34
+ required: false
35
+ type: string
36
+ default: '{}'
37
+ required-job-names-json:
38
+ description: Exact aggregate gate job names to verify from the source run's complete attempt-job listing.
39
+ required: false
40
+ type: string
41
+ default: '[]'
42
+ outputs:
43
+ reuse:
44
+ description: True only when a matching recent source receipt was verified.
45
+ value: ${{ jobs.verify.outputs.reuse }}
46
+
47
+ permissions:
48
+ actions: read
49
+ contents: read
50
+ pull-requests: read
51
+
52
+ jobs:
53
+ verify:
54
+ name: Verify source receipt
55
+ if: >-
56
+ vars.CI_BILLING_PAUSED != 'true' && inputs.enabled == true &&
57
+ inputs.phase == 'verify' && inputs.mode == 'release'
58
+ runs-on: ubuntu-slim
59
+ timeout-minutes: 15
60
+ outputs:
61
+ reuse: ${{ steps.verify.outputs.reuse }}
62
+ steps:
63
+ - name: Checkout release PR source
64
+ id: source
65
+ continue-on-error: true
66
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
67
+ with:
68
+ persist-credentials: false
69
+ fetch-depth: 0
70
+ - name: Checkout runtime
71
+ id: runtime
72
+ if: steps.source.outcome == 'success'
73
+ continue-on-error: true
74
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
75
+ with:
76
+ persist-credentials: false
77
+ repository: ${{ inputs.runtime-repository }}
78
+ ref: ${{ inputs.runtime-ref }}
79
+ path: .github/.code-foundry
80
+ sparse-checkout: |
81
+ src/commands/qualification-receipt.mjs
82
+ src/lib
83
+ src/runtime-core.mjs
84
+ src/runtime.mjs
85
+ - name: Install runtime
86
+ id: install
87
+ if: steps.runtime.outcome == 'success'
88
+ continue-on-error: true
89
+ run: mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
90
+ - name: Set up Node.js 24.18.0
91
+ id: node
92
+ if: steps.install.outcome == 'success'
93
+ continue-on-error: true
94
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
95
+ with:
96
+ node-version: 24.18.0
97
+ - name: Check version-only release diff
98
+ id: release-policy
99
+ if: steps.node.outcome == 'success'
100
+ continue-on-error: true
101
+ env:
102
+ FOUNDRY_BASE_SHA: ${{ github.event.pull_request.base.sha }}
103
+ FOUNDRY_HEAD_REF: ${{ github.event.pull_request.head.ref }}
104
+ FOUNDRY_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
105
+ FOUNDRY_REPOSITORY: ${{ github.repository }}
106
+ RUNTIME_PATH: ${{ runner.temp }}/code-foundry
107
+ run: node "$RUNTIME_PATH/src/runtime.mjs" validation release_diff
108
+ - name: Verify source qualification receipt
109
+ id: verify
110
+ if: always()
111
+ continue-on-error: true
112
+ env:
113
+ SOURCE_READY: ${{ steps.source.outcome }}
114
+ RUNTIME_READY: ${{ steps.install.outcome }}
115
+ NODE_READY: ${{ steps.node.outcome }}
116
+ POLICY_READY: ${{ steps.release-policy.outcome }}
117
+ GITHUB_TOKEN: ${{ github.token }}
118
+ RUNTIME_PATH: ${{ runner.temp }}/code-foundry
119
+ RUNTIME_REPOSITORY: ${{ inputs.runtime-repository }}
120
+ FOUNDRY_MODE: ${{ inputs.mode }}
121
+ FOUNDRY_CODEQL_ENABLED: ${{ inputs.codeql-enabled }}
122
+ FOUNDRY_REQUIRED_JOB_NAMES_JSON: ${{ inputs.required-job-names-json }}
123
+ run: |
124
+ if [ "$SOURCE_READY" = success ] && [ "$RUNTIME_READY" = success ] && [ "$NODE_READY" = success ] && [ "$POLICY_READY" = success ] && [ -f "$RUNTIME_PATH/src/commands/qualification-receipt.mjs" ]; then
125
+ node "$RUNTIME_PATH/src/commands/qualification-receipt.mjs" verify >> "$GITHUB_OUTPUT"
126
+ else
127
+ echo 'reuse=false' >> "$GITHUB_OUTPUT"
128
+ echo 'reason=qualification or version-only release policy unavailable; using full validation' >> "$GITHUB_OUTPUT"
129
+ fi
130
+
131
+ produce:
132
+ name: Produce source receipt
133
+ if: >-
134
+ vars.CI_BILLING_PAUSED != 'true' && inputs.enabled == true &&
135
+ inputs.phase == 'produce' && inputs.mode == 'audit'
136
+ runs-on: ubuntu-slim
137
+ timeout-minutes: 10
138
+ steps:
139
+ - name: Checkout tested source tree
140
+ id: source
141
+ continue-on-error: true
142
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
143
+ with:
144
+ persist-credentials: false
145
+ ref: ${{ github.sha }}
146
+ fetch-depth: 2
147
+ - name: Checkout runtime
148
+ id: runtime
149
+ if: steps.source.outcome == 'success'
150
+ continue-on-error: true
151
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
152
+ with:
153
+ persist-credentials: false
154
+ repository: ${{ inputs.runtime-repository }}
155
+ ref: ${{ inputs.runtime-ref }}
156
+ path: .github/.code-foundry
157
+ sparse-checkout: |
158
+ src/commands/qualification-receipt.mjs
159
+ src/lib
160
+ - name: Install runtime
161
+ id: install
162
+ if: steps.runtime.outcome == 'success'
163
+ continue-on-error: true
164
+ run: mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
165
+ - name: Set up Node.js 24.18.0
166
+ id: node
167
+ if: steps.install.outcome == 'success'
168
+ continue-on-error: true
169
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
170
+ with:
171
+ node-version: 24.18.0
172
+ - name: Create qualification receipt
173
+ id: produce
174
+ if: always()
175
+ continue-on-error: true
176
+ env:
177
+ SOURCE_READY: ${{ steps.source.outcome }}
178
+ RUNTIME_READY: ${{ steps.install.outcome }}
179
+ NODE_READY: ${{ steps.node.outcome }}
180
+ GITHUB_TOKEN: ${{ github.token }}
181
+ RUNTIME_PATH: ${{ runner.temp }}/code-foundry
182
+ RUNTIME_REPOSITORY: ${{ inputs.runtime-repository }}
183
+ FOUNDRY_MODE: ${{ inputs.mode }}
184
+ FOUNDRY_JOB_RESULTS_JSON: ${{ inputs.job-results-json }}
185
+ FOUNDRY_REQUIRED_JOB_NAMES_JSON: ${{ inputs.required-job-names-json }}
186
+ run: |
187
+ if [ "$SOURCE_READY" = success ] && [ "$RUNTIME_READY" = success ] && [ "$NODE_READY" = success ] && [ -f "$RUNTIME_PATH/src/commands/qualification-receipt.mjs" ]; then
188
+ node "$RUNTIME_PATH/src/commands/qualification-receipt.mjs" produce >> "$GITHUB_OUTPUT"
189
+ else
190
+ echo 'reuse=false' >> "$GITHUB_OUTPUT"
191
+ echo 'reason=receipt setup unavailable' >> "$GITHUB_OUTPUT"
192
+ fi
193
+ - name: Upload qualification receipt
194
+ if: steps.produce.outputs.reuse == 'true'
195
+ continue-on-error: true
196
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
197
+ with:
198
+ name: code-foundry-qualification-v2-${{ github.run_id }}-${{ github.run_attempt }}
199
+ path: qualification-receipt.json
200
+ if-no-files-found: error
201
+ retention-days: 7
@@ -16,9 +16,6 @@ on:
16
16
  required: false
17
17
  type: boolean
18
18
  default: false
19
- secrets:
20
- NPM_TOKEN:
21
- required: false
22
19
 
23
20
  permissions:
24
21
  attestations: read
@@ -88,7 +85,6 @@ jobs:
88
85
  contents: read
89
86
  id-token: write
90
87
  env:
91
- HAS_NPM_TOKEN: ${{ secrets.NPM_TOKEN != '' }}
92
88
  RELEASE_TAG: ${{ inputs.tag }}
93
89
  RELEASE_ASSET: ${{ inputs.asset }}
94
90
  steps:
@@ -98,16 +94,9 @@ jobs:
98
94
  persist-credentials: false
99
95
  ref: ${{ github.sha }}
100
96
  - name: Setup Node for trusted publishing
101
- if: env.HAS_NPM_TOKEN != 'true'
102
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
103
- with:
104
- node-version: '24'
105
- - name: Setup Node for token publishing
106
- if: env.HAS_NPM_TOKEN == 'true'
107
97
  uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
108
98
  with:
109
99
  node-version: '24'
110
- registry-url: https://registry.npmjs.org
111
100
  - name: Retrieve only this run attempt's evidence
112
101
  env:
113
102
  GH_TOKEN: ${{ github.token }}
@@ -124,7 +113,6 @@ jobs:
124
113
  - name: Reverify and publish the tested tarball without lifecycle hooks
125
114
  env:
126
115
  GH_TOKEN: ${{ github.token }}
127
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
128
116
  run: |
129
117
  set -euo pipefail
130
118
  node src/commands/qualified-publication.mjs publish \