Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ updates:
directory: /
schedule:
interval: weekly
cooldown:
# zizmor dependabot-cooldown (#1156 B2.6): let fresh action releases
# bake for a week before Dependabot proposes them.
default-days: 7
open-pull-requests-limit: 5
32 changes: 31 additions & 1 deletion .github/workflows/autoflow-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,33 @@ jobs:
# never checkout's default synthetic merge ref.
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
persist-credentials: false
# #1156 (B2.6): mature OSS governance gates (ADR-0144) — fail fast,
# before the heavy matrix. Binaries pinned by version + SHA-256;
# zizmor-action pinned in tools/check-action-pins.ts.
- name: actionlint (workflow lint)
run: |
curl -sSfL -o /tmp/actionlint.tar.gz \
https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz
echo "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 /tmp/actionlint.tar.gz" | sha256sum -c -
tar -xzf /tmp/actionlint.tar.gz -C /tmp actionlint
/tmp/actionlint -color
# v0.6.3
- uses: zizmorcore/zizmor-action@70fb788f84895a7701f5643d103d587e460b5c99
with:
# Offline audits only: this gate must be deterministic and
# reproducible locally (`zizmor --offline .github/workflows
# .github/actions`); network-dependent audits stay out of CI.
online-audits: false
advanced-security: false
version: '1.30.0'
- name: gitleaks (secret scan)
run: |
curl -sSfL -o /tmp/gitleaks.tar.gz \
https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz
echo "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb /tmp/gitleaks.tar.gz" | sha256sum -c -
tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks
/tmp/gitleaks git --redact --verbose .
- uses: ./.github/actions/setup-deno-workspace
- name: Install Playwright browsers
# All three engines up front: the gate's fixture:request-time:gate
Expand All @@ -66,6 +93,7 @@ jobs:
with:
# #1156 R11: same exact-SHA expression as every required job.
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: ./.github/actions/setup-deno-workspace
# v7.0.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
Expand Down Expand Up @@ -96,7 +124,7 @@ jobs:
OPEN_ELEMENT_PORT=4891 OPEN_ELEMENT_HOST=127.0.0.1 node dist/server/serve.mjs &
server_pid=$!
trap 'kill $server_pid 2>/dev/null || true' EXIT
for i in $(seq 1 50); do
for _ in $(seq 1 50); do
curl -sf -o /dev/null http://127.0.0.1:4891/ && break
sleep 0.2
done
Expand Down Expand Up @@ -127,6 +155,7 @@ jobs:
with:
# #1156 R11: same exact-SHA expression as every required job.
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: ./.github/actions/setup-deno-workspace
# v7.0.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
Expand Down Expand Up @@ -156,6 +185,7 @@ jobs:
with:
# #1156 R11: the aggregation job checks out the exact SHA it attests.
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: ./.github/actions/setup-deno-workspace
- name: Write exact-SHA PR CI evidence record
env:
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/autoflow-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
actions: read
steps:
# v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # zizmor: ignore[artipacked] the release lane pushes the immutable release tag with this credential (tools/autoflow/release.ts); every other workflow sets persist-credentials: false
with:
ref: main
fetch-depth: 0
Expand All @@ -57,7 +57,7 @@ jobs:
# and switching the whole release lane to Node 24 would still leave
# the floor to whatever npm that image bundles, so the floor is
# pinned explicitly here and verified before publish runs.
run: |
run: | # zizmor: ignore[adhoc-packages] the npm floor is pinned and asserted immediately below; trusted publishing requires it
npm install -g "npm@^11.5.1"
actual="$(npm --version)"
minimum="11.5.1"
Expand Down Expand Up @@ -111,4 +111,6 @@ jobs:
RELEASE_DRY_RUN: ${{ inputs.dry_run && '--dry-run' || '' }}
PR_CI_EVIDENCE: .artifacts/pr-ci/pr-full-ci-evidence.json
run: |
# shellcheck disable=SC2086 # RELEASE_DRY_RUN is intentionally
# word-split: it is either empty or the single flag --dry-run.
deno task autoflow:publish-existing --to "$RELEASE_VERSION" --pr-ci "$PR_CI_EVIDENCE" $RELEASE_DRY_RUN
2 changes: 2 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ jobs:
- name: Checkout repository
# v7.0.1
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false

- name: Initialize CodeQL
# v4.37.9
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/fullstack-deploy-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ jobs:
steps:
# v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: ./.github/actions/setup-deno-workspace

- name: Build the Workers bundle
Expand Down Expand Up @@ -187,7 +189,7 @@ jobs:
set -e
mkdir -p .smoke
record() { echo "{\"check\":\"$1\",\"result\":\"$2\"}" >> .smoke/results.jsonl; }
for i in 1 2 3 4 5 6; do
for _ in 1 2 3 4 5 6; do
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "$WORKER_URL/" || true)
[ "$code" = "200" ] && break
sleep 10
Expand Down Expand Up @@ -336,6 +338,8 @@ jobs:
eicar_name="scanner-eicar-$suffix.txt"
printf 'OpenElement scanner qualification clean fixture.\n' > "$clean_file"
# Standard EICAR test string, generated only in the ephemeral runner.
# shellcheck disable=SC2016 # the single-quoted EICAR signature must
# not expand its $ sequences.
printf '%s' 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > "$eicar_file"
for fixture in clean eicar; do
name_var="${fixture}_name"; file_var="${fixture}_file"
Expand Down Expand Up @@ -415,6 +419,10 @@ jobs:
if: always()
env:
WORKER_URL: https://openelement-ref-starter.freemanzheng.workers.dev
# zizmor: ignore[template-injection] every expansion below is
# GitHub-controlled context (job.status, github.run_id,
# steps.*.outcome) — no attacker-controllable input reaches this
# report writer.
run: |
checks='[]'
if [ -f .smoke/results.jsonl ]; then
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/nightly-stress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
steps:
# v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: ./.github/actions/setup-deno-workspace
- name: Run representative 30-minute workload
env:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/published-consumers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ jobs:
steps:
# v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: ./.github/actions/setup-deno-workspace
- name: Generate and exercise the published starter
env:
Expand All @@ -45,6 +47,8 @@ jobs:
steps:
# v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: ./.github/actions/setup-deno-workspace
- name: Install Chromium for browser-backed consumer smoke
run: ./node_modules/.bin/playwright install --with-deps chromium
Expand Down
12 changes: 10 additions & 2 deletions .github/workflows/supabase-project-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ jobs:
steps:
# v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false

# v1, pinned 2026-08-17
- uses: supabase/setup-cli@ab058987d8d6c725971f6cf9d0b5c98467e30bd1
Expand Down Expand Up @@ -75,6 +77,8 @@ jobs:
steps:
# v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: ./.github/actions/setup-deno-workspace

- name: Require dedicated migration credentials
Expand Down Expand Up @@ -177,7 +181,7 @@ jobs:
set -euo pipefail
deno task build
OPEN_ELEMENT_PORT=4173 nohup deno task start > "$GITHUB_WORKSPACE/.smoke/server.log" 2>&1 &
for i in $(seq 1 30); do
for _ in $(seq 1 30); do
if curl -s -o /dev/null http://127.0.0.1:4173/; then break; fi
sleep 1
done
Expand Down Expand Up @@ -379,7 +383,7 @@ jobs:
# instead of racing the invalidation; the assertion itself — the
# object must become inaccessible — is unchanged.
after_delete=""
for i in $(seq 1 12); do
for _ in $(seq 1 12); do
after_delete=$(curl -s -o /dev/null -w '%{http_code}' \
"$SUPABASE_URL/storage/v1/object/notes-attachments/$STORAGE_POLICY_KEY" \
-H "apikey: $SUPABASE_ANON_KEY" -H "Authorization: Bearer $token_a")
Expand Down Expand Up @@ -477,6 +481,10 @@ jobs:

- name: Write the redacted smoke report
if: always()
# zizmor: ignore[template-injection] every expansion below is
# GitHub-controlled context (job.status, github.run_id,
# steps.*.outcome, inputs.migration_mode) — no attacker-controllable
# input reaches this report writer.
run: |
matrix='[]'
if [ -f .smoke/results.jsonl ]; then
Expand Down
8 changes: 8 additions & 0 deletions .github/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# zizmor configuration (#1156 B2.6). Findings are fixed, not suppressed; the
# only disabled audit is a style preference already covered by an owned gate.
rules:
self-repository:
# The repository standardizes on the `./.github/...` local-action form;
# tools/check-action-pins.ts already audits every `uses:` clause, so the
# `$/` prefix would add a second convention without new evidence.
disable: true
20 changes: 20 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Gitleaks configuration for OpenElement (#1156 B2.6).
# Extends the default rule set; the allowlist below covers deliberate
# placeholder credentials used in tests and documentation. Real credential
# material must never appear here — fix the leak, do not allowlist it.

[extend]
useDefault = true

[allowlist]
description = "Deliberate non-secret placeholders"
regexTarget = "line"
regexes = [
# Test fixtures: intentionally invalid Stripe-shaped placeholders used to
# assert checkoutConfiguration mode validation (never real credentials).
'''sk_live_wrong''',
'''rk_(?:test|live)_restricted''',
# Runbook example (git history): a shell variable reference, not a
# credential value.
'''-u\s+["']?\$STRIPE_SECRET_KEY''',
]
14 changes: 14 additions & 0 deletions .markdownlint-cli2.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "https://raw.githubusercontent.com/DavidAnson/markdownlint-cli2/v0.23.2/schema/markdownlint-cli2-config-schema.json",
"gitignore": true,
"config": {
"default": false,
"MD001": true,
"MD009": { "br_spaces": 2 },
"MD011": true,
"MD012": true,
"MD024": { "siblings_only": true },
"MD042": true,
"MD047": true
}
}
5 changes: 4 additions & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"fullstack:evidence-freshness": "deno run --allow-env --allow-net=api.github.com tools/check-evidence-freshness.ts",
"fullstack:cloudflare-config-check": "deno test --allow-read tools/render-cloudflare-async-config.test.ts && deno task --cwd examples/supabase-cloudflare-starter build && deno task --cwd examples/supabase-cloudflare-starter nitro:build && deno run --allow-read --allow-write tools/render-cloudflare-async-config.ts examples/supabase-cloudflare-starter/wrangler.jsonc examples/supabase-cloudflare-starter/.wrangler-async.generated.json && deno run --allow-run=deno tools/run-wrangler-dry-run.ts examples/supabase-cloudflare-starter/.wrangler-async.generated.json && rm examples/supabase-cloudflare-starter/.wrangler-async.generated.json",
"arch:check": "deno run --allow-read --allow-run tools/check-architecture-contract.ts",
"type-safety:check": "deno run --allow-read tools/check-type-safety.ts",
"lint:markdown": "deno run -A npm:markdownlint-cli2@0.23.2 \"**/*.md\"",
"deno-api:check": "deno run --allow-read --allow-env tools/check-deno-api-free.ts",
"text-integrity:check": "deno run --allow-read --allow-run=git tools/check-docs-truth.ts --check=text",
"audit:citations:check": "deno run -A tools/check-audit-citations.ts",
Expand Down Expand Up @@ -160,6 +160,9 @@
"tags": [
"recommended"
],
"include": [
"no-explicit-any"
],
"exclude": [
"no-sloppy-imports"
]
Expand Down
1 change: 1 addition & 0 deletions examples/supabase-cloudflare-starter/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions tools/autoflow/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,18 +320,20 @@ const GATES: readonly GateDefinition[] = [
/^tools\/check-signal-protocol-boundary\.ts$/,
],
},
{
name: 'type-safety:check',
command: ['deno', 'task', 'type-safety:check'],
tiers: ['ci', 'release'],
triggers: [/^packages\//, /^tools\//, /^www\//, /^deno\.json$/],
},
{
name: 'deno-api:check',
command: ['deno', 'task', 'deno-api:check'],
tiers: ['ci', 'release'],
triggers: [/^packages\/(element|ui|app)\/src\//],
},
{
// #1156 (B2.6): markdownlint-cli2 owns Markdown structure per ADR-0144
// (thin .markdownlint-cli2.jsonc config; no bespoke checker).
name: 'lint:markdown',
command: ['deno', 'task', 'lint:markdown'],
tiers: ['push', 'ci', 'release'],
triggers: [/\.md$/, /^\.markdownlint-cli2\.jsonc$/, /^deno\.json$/],
},
{
name: 'text-integrity:check',
command: ['deno', 'task', 'text-integrity:check'],
Expand Down
2 changes: 2 additions & 0 deletions tools/check-action-pins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const ACTION_VERSION_PINS = new Map([
['github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3', 'v4.37.6'],
['github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938', 'v4.37.9'],
['github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938', 'v4.37.9'],
// #1156 (B2.6): zizmor workflow-security gate (ADR-0144).
['zizmorcore/zizmor-action@70fb788f84895a7701f5643d103d587e460b5c99', 'v0.6.3'],
]);

// Repos that carry an approved pin above. A full-SHA use of one of these repos
Expand Down
1 change: 0 additions & 1 deletion tools/check-architecture-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,6 @@ export function isProductionSource(path: string): boolean {
// Test files that exercise the architecture contract necessarily contain
// escape tokens, so they are excluded from production scanning.
if (path === 'tools/check-architecture-contract.test.ts') return false;
if (path === 'tools/check-type-safety.test.ts') return false;
if (path.startsWith('packages/') && path.includes('/src/') && /\.(ts|tsx)$/.test(path)) {
return true;
}
Expand Down
23 changes: 5 additions & 18 deletions tools/check-repo-hygiene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,17 @@ const allowedTrackedIgnoredPaths = [
/^vendor\/jsr\.io\/(@[^/]+\/)?[^/]+\/LICENSE$/,
];

// Secret scanning: tracked credential files are always failures, and
// credential-shaped content in active source files fails the gate. These
// patterns intentionally stay narrow to keep false positives at zero.
// Placeholder templates (.env.example/.env.sample/.env.template) are
// allowed by name — the content scan below still applies to them, so a
// template carrying real credentials still fails.
// Tracked credential files are always failures. The content-level secret
// scan is owned by gitleaks (#1156 B2.6, .gitleaks.toml); this file-name
// tripwire stays because gitleaks does not flag a tracked-but-empty
// credential file. Placeholder templates (.env.example/.env.sample/
// .env.template) are allowed by name.
const allowedCredentialTemplates = /(?:^|\/)\.env(?:\.example|\.sample|\.template)$/;
const forbiddenTrackedSecretFiles = [
/(?:^|\/)\.env(?:\.[^/]+)?$/,
/(?:^|\/)[^/]+\.pem$/,
/(?:^|\/)id_rsa(?:\.pub)?$/,
];
const SECRET_CONTENT_PATTERNS = [
/-----BEGIN (?:RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/,
/\bAKIA[0-9A-Z]{16}\b/,
/\bgh[pousr]_[A-Za-z0-9]{36,}\b/,
/\bxox[baprs]-[A-Za-z0-9-]{20,}\b/,
];

// Large tracked binaries: intentional design/e2e/fixture assets are listed;
// anything else above 1 MiB should not enter the repository.
Expand Down Expand Up @@ -165,12 +158,6 @@ for (const file of files.filter(isActiveScanFile)) {
});
}
}
for (const pattern of SECRET_CONTENT_PATTERNS) {
if (pattern.test(text)) {
failures.push({ path: file, message: 'credential-shaped content detected' });
break;
}
}
}

for (const file of files) {
Expand Down
Loading
Loading