Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
fc2faa4
docs(product): add product + UX specs and v4.0.0 changelog
claude Jun 11, 2026
c850c3d
refactor(core): split skill script.py into stdlib-only prd_taskmaster…
claude Jun 11, 2026
1befd7e
feat(parallel): move research fan-out engine into package + unified CLI
claude Jun 11, 2026
e384d9c
feat(core): import plugin state machine, ship-check, mode recommender
claude Jun 11, 2026
611189a
feat(skill): v4 SKILL.md + phases (the Atlas engine), drop stale files
claude Jun 11, 2026
4c67714
feat(plugin): rewire FastMCP server onto package + atlas-go→prd-taskm…
claude Jun 11, 2026
5461fd1
test: consolidate suite into core/mcp/plugin, fix ship-check to live …
claude Jun 11, 2026
2f5d9f6
build(install+ci): v4.0.0 installer (package + /atlas alias) and CI
claude Jun 11, 2026
4fb273c
docs(readme): v4 open-core storefront rewrite
claude Jun 11, 2026
f1353d7
chore(brand): scrub residual prd-taskmaster-v2 strings in package code
claude Jun 11, 2026
cbe55a1
docs(dogfood): Phase B run evidence — full pipeline green, 4 findings
claude Jun 11, 2026
617dce4
fix(engine): resolve all four Phase B dogfood findings
claude Jun 11, 2026
c0463f1
feat(fleet): wave scheduler core — ready_set + compute_waves (REQ-001…
claude Jun 11, 2026
6769270
feat(fleet): detect_atlas_launcher() probe (REQ-004)
claude Jun 11, 2026
ef485fe
feat(fleet): premium tier + Atlas Fleet recommendation flip (REQ-005)
claude Jun 11, 2026
b6df1fb
feat(fleet): fleet-waves CLI + compute_fleet_waves MCP tool (REQ-003)
claude Jun 11, 2026
6f653b0
feat(fleet): execute-fleet orchestrator skill + worker contract (REQ-…
claude Jun 11, 2026
0531959
feat(fleet): handoff Mode D selectable on premium tier (REQ-005 surface)
claude Jun 11, 2026
ba3b38d
feat(fleet): .atlas-ai/fleet.json routing config (REQ-010)
claude Jun 11, 2026
a34c77a
fix(fleet): conform execute-fleet worker inbox calls to launcher runt…
claude Jun 11, 2026
2be055c
fix(fleet): worker contract — evidence files are final-verification only
claude Jun 11, 2026
6db8179
fix(shipcheck): Gate 2 accepts flat tasks.json + tagged fallback
claude Jun 11, 2026
4c49224
docs(dogfood): first live Atlas Fleet run — SHIP_CHECK_OK (B-Task 12)
claude Jun 11, 2026
debad39
feat(ux): engine_preflight — one batched Phase-1 call (MCP tool + CLI)
claude Jun 11, 2026
3d46b7e
fix(detect): extract semver from task-master --version (telemetry-not…
claude Jun 11, 2026
b339b51
feat(ux): MCP-first phases + autonomous-after-approval rule
claude Jun 11, 2026
c5e5eb1
feat(license): key format spec + signing tool (task 1)
claude Jun 11, 2026
cf9ee58
chore(fleet): report key chunk completion (task 1)
claude Jun 11, 2026
42a5ce0
merge(fleet): wave 1 — chunk KEY (task 1) into integration
claude Jun 11, 2026
3d3e009
feat(license): add client verifier module (task 2)
claude Jun 11, 2026
4f92297
feat(worker): scaffold Cloudflare Worker backend (task 4)
claude Jun 11, 2026
8dd1f8b
feat(license): add activation and premium gating (task 3)
claude Jun 11, 2026
4305edd
docs(fleet): report client chunk outcome
claude Jun 11, 2026
54e780e
merge(fleet): wave 2 — chunk CLIENT (tasks 2,3) into integration
claude Jun 11, 2026
be8374e
feat(stripe): handle billing webhooks and license issuance (task 5)
claude Jun 11, 2026
313c5bd
test(fleet): legacy premium-detection test now injects an active lice…
claude Jun 11, 2026
20615d5
feat(email): deliver license keys via Resend (task 6)
claude Jun 11, 2026
de890c7
feat(worker): implement license refresh endpoint (task 7)
claude Jun 11, 2026
538c70a
feat(worker): add telemetry endpoint and KPI storage (task 10)
claude Jun 11, 2026
42ea158
docs(fleet): report backend chunk completion
claude Jun 11, 2026
1afba34
merge(fleet): wave 2 — chunk BACKEND (tasks 4,5,6,7,10) into integration
claude Jun 11, 2026
d74bcc8
feat(license): add silent refresh flow (task 8)
claude Jun 11, 2026
22c87b8
docs(checkout): record Atlas Pro checkout contract (task 9)
claude Jun 11, 2026
5debf4f
feat(telemetry): add anonymous client events (task 11)
claude Jun 11, 2026
ac26645
feat(telemetry): send install pings (task 12)
claude Jun 11, 2026
c691f49
docs(fleet): add NET completion report
claude Jun 11, 2026
4148c7c
merge(fleet): wave 3 — chunk NET (tasks 8,9,11,12) into integration
claude Jun 11, 2026
380f588
feat(ux): conform terminal phase grammar (task 13)
claude Jun 11, 2026
5c97ed1
feat(onboarding): verify first-run quickstart (task 15)
claude Jun 11, 2026
8c99376
test(ux): enforce vocabulary and paywall lint (task 14)
claude Jun 11, 2026
bc07256
feat(ops): add KPI snapshot and release evidence (task 16)
claude Jun 11, 2026
1bb2813
docs(fleet): report UXREL completion
claude Jun 11, 2026
b3efd7a
merge(fleet): wave 4 — chunk UXREL (tasks 13,15,14,16) into integration
claude Jun 11, 2026
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
18 changes: 18 additions & 0 deletions .atlas-ai/cdd/task-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"task": 1,
"given": "Atlas Pro needs portable license keys signed with Ed25519 and verified without private-key material in the repo",
"when": "the Python CLI, TypeScript worker signer, committed vectors, and documentation are exercised",
"then": [
"license keys use ATLAS-<base64url(payload)>.<base64url(sig)> with canonical JSON payload bytes",
"payloads contain lid, sub, plan, iat, exp, and v fields with v equal to 1",
"Ed25519 signing and verification pass RFC 8032 vectors",
"valid, expired, tampered-payload, and signature-mismatch fixtures produce their expected verdicts",
"Python and TypeScript signers produce byte-identical keys for fixture payloads",
"private signing material is ignored and repository scanning fails on committed private-key material"
],
"evidence_required": [
"python3 -m pytest tests/license/ -q",
"python3 -m pytest tests/ -q",
"git diff --cached --name-only before commit includes forced .atlas-ai/cdd/task-1.json"
]
}
19 changes: 19 additions & 0 deletions .atlas-ai/cdd/task-10.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"task": 10,
"given": "The Worker exposes a public telemetry endpoint for minimal Atlas usage events",
"when": "POST /telemetry receives valid events, malformed payloads, storage failures, or KPI query fixtures",
"then": [
"valid install, atlas_invoked, reach_execute, and ship_check_ok payloads return 204",
"schema violations return 400 and method violations return 405",
"valid events are inserted into D1 telemetry_events",
"valid events call Analytics Engine writeDataPoint with blobs [event, version, os] and indexes [install_id]",
"storage sink failures are logged without changing a valid request response",
"documented D1 KPI queries compute A1, A3, AC1, and AC2 from seeded rows"
],
"evidence_required": [
"workers/test/telemetry.test.ts red/green output",
"D1 migration 0003 applied locally",
"Worker typecheck and vitest output",
"blocked deploy/smoke logged because production deploy is intentionally skipped"
]
}
15 changes: 15 additions & 0 deletions .atlas-ai/cdd/task-11.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"task": 11,
"given": "A local Atlas install runs CLI and pipeline workflows",
"when": "telemetry is enabled and lifecycle events occur",
"then": [
"the client generates a stable anonymous install_id under ~/.atlas-ai",
"telemetry POST payloads contain exactly install_id, event, version, and os",
"ATLAS_TELEMETRY=0 and telemetry:false config opt-outs prevent install_id creation and network calls",
"pipeline and ship-check hooks are best-effort and never alter return values"
],
"evidence_required": [
"python3 -m pytest tests/test_telemetry.py -q",
"python3 -m pytest tests/ -x -q"
]
}
16 changes: 16 additions & 0 deletions .atlas-ai/cdd/task-12.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"task": 12,
"given": "A user installs Atlas through install.sh or the npm package",
"when": "installation completes successfully",
"then": [
"install.sh sends a best-effort install telemetry event unless opted out",
"--no-telemetry and ATLAS_TELEMETRY=0 suppress the install ping before python is invoked",
"package.json postinstall sends the same best-effort install event unless opted out",
"README discloses exact telemetry fields, event names, and all opt-out mechanisms"
],
"evidence_required": [
"bash tests/install/test_install_telemetry.sh",
"python3 -m pytest tests/install tests/test_telemetry.py -q",
"python3 -m pytest tests/ -x -q"
]
}
1 change: 1 addition & 0 deletions .atlas-ai/cdd/task-13.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"task":13,"given":"The pipeline has internal phases and user-facing gate results","when":"terminal UX output is rendered for setup, discovery, generate, and handoff","then":["phase headers use the Atlas PHASE n/4 grammar","gate output uses Gate passed/Gate blocked plus Fix lines instead of raw JSON","user-facing labels avoid banned internal jargon","locked Atlas Fleet paywall text states $29/mo inline and never defaults to paid mode"],"evidence_required":["pytest tests/core/test_render.py -q","grep audits for phase headers and gate lines in setup/discover/generate/handoff skills","python3 -m pytest tests/ -q shows no new failures vs base"]}
1 change: 1 addition & 0 deletions .atlas-ai/cdd/task-14.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"task":14,"given":"User-facing UX strings and Pro paywall surfaces are present in skills, phase docs, templates, README, installer, hooks, and recommendation code","when":"the UX conformance lint runs in pytest and CI","then":["Markdown and Python user-facing strings are extracted deterministically","banned jargon primary labels are reported with file:line:term","load-bearing identifiers such as .atlas-ai/cdd, requiresCDD, and the ralph-loop capability key are allowed","Atlas Fleet paywall surfaces state $29/mo inline, use atlas-ai.au/pro, and never default-select locked Fleet"],"evidence_required":["python3 -m pytest tests/test_ux_conformance.py -q","python3 -m pytest tests/ -x -q shows no new failures vs base"]}
1 change: 1 addition & 0 deletions .atlas-ai/cdd/task-15.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"task":15,"given":"A fresh user installs and runs Atlas from a clean environment","when":"setup, install, and the quickstart walkthrough execute without local developer paths","then":["setup copies customizations from the installed skill-relative skel directory","install.sh handles the task-master-ai peer dependency with clear success and failure grammar","the deterministic quickstart walkthrough passes without credentials","README quickstart matches observed installer output"],"evidence_required":["python3 -m pytest tests/plugin/test_setup_portability.py -q","python3 -m pytest tests/core/test_quickstart_walkthrough.py -q","bash tests/scripts/quickstart-walkthrough.sh","python3 -m pytest tests/ -x -q shows no new failures vs base"]}
1 change: 1 addition & 0 deletions .atlas-ai/cdd/task-16.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"task":16,"given":"Release validation needs locally-generatable KPI and ship-check evidence","when":"ops runs the KPI snapshot and release ship-check from this branch","then":["kpi-snapshot.sh prints A1, A3, AC1, AC2, and C1 rows for last-7d, last-30d, and all-time","unconfigured analytics mode exits 0 with clear not-configured notices and C1 n/a when license telemetry is absent","ops runbook documents environment setup, queries, and weekly review","release evidence records full suite, UX lint, ship-check, and live purchase as blocked when credentials/deploy are unavailable"],"evidence_required":["python3 -m pytest tests/core/test_kpi_snapshot.py -q","python3 scripts/ops/kpi-snapshot.sh or bash scripts/ops/kpi-snapshot.sh output","python3 -m pytest tests/ -x -q","python3 skel/ship-check.py --cwd REPO_PATH"]}
1 change: 1 addition & 0 deletions .atlas-ai/cdd/task-2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"task":2,"given":"an offline Atlas Pro license key signed with the shipped Ed25519 public key","when":"the client parses, verifies, evaluates, saves, and loads the key without network access or third-party runtime dependencies","then":["RFC 8032 Ed25519 verification accepts valid vectors and rejects tampering","ATLAS-v1 license keys parse into canonical payload bytes and signature bytes with structured invalid results","status resolves to active, grace, expired, or invalid with exp-includes-grace semantics","valid licenses persist under ~/.atlas-ai/license.json with private permissions"],"evidence_required":["python3 -m pytest tests/core/test_license.py -q","python3 -m pytest tests/ -x -q"]}
1 change: 1 addition & 0 deletions .atlas-ai/cdd/task-3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"task":3,"given":"a user has an Atlas Pro license key and atlas-launcher may be registered","when":"they activate the key through CLI or MCP and capability detection runs","then":["license-activate accepts a key argument and renders the UX-SPEC status block without raw JSON by default","valid active or grace keys are persisted and invalid or expired keys are rejected","detect-capabilities exposes license_status and only unlocks premium tier when atlas-launcher is registered and the license is active or grace","MCP exposes license_activate and license-aware detect_capabilities","handoff skill copy reflects active, grace, expired, and missing license states with inline Pro price and /pro link"],"evidence_required":["python3 -m pytest tests/core/test_license_activate.py tests/core/test_capabilities.py tests/mcp/test_mcp_tools.py tests/plugin/test_skill_files.py -q","python3 -m pytest tests/ -x -q"]}
18 changes: 18 additions & 0 deletions .atlas-ai/cdd/task-4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"task": 4,
"given": "A greenfield Worker backend for Atlas Pro billing and telemetry",
"when": "the Worker project is scaffolded with D1, route skeletons, local tests, deployment guardrails, and secret hygiene",
"then": [
"unknown routes return 404",
"the LICENSE_DB D1 binding and migrations create license and webhook idempotency tables",
"the public route contracts exist for /stripe/webhook, /license/refresh, and /telemetry",
"deployment and secret-scanning procedures are documented and locally verifiable without committing secrets"
],
"evidence_required": [
"npm test Worker vitest output",
"wrangler d1 migrations apply LICENSE_DB --local output",
"wrangler deploy --dry-run output or credential-aware blocked log",
"secret scan output",
"FLEET-LOG-BACKEND.md PASS/BLOCKED line"
]
}
18 changes: 18 additions & 0 deletions .atlas-ai/cdd/task-5.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"task": 5,
"given": "Stripe sends signed billing webhooks to the Worker",
"when": "checkout, invoice, cancellation, duplicate, unsigned, or forged webhook requests are delivered",
"then": [
"invalid or missing signatures return 400 without mutating D1",
"replayed event IDs return 200 without duplicate side effects",
"checkout.session.completed creates a license row and signed ATLAS key",
"invoice.paid extends the existing license expiry and reissues a key",
"customer.subscription.deleted marks the license cancelled without issuing a key"
],
"evidence_required": [
"workers/test/stripe.test.ts red/green output",
"Worker vitest output",
"typecheck output",
"blocked Stripe CLI replay logged because Stripe credentials are absent"
]
}
18 changes: 18 additions & 0 deletions .atlas-ai/cdd/task-6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"task": 6,
"given": "A Stripe checkout or renewal webhook produces a signed Atlas Pro license key",
"when": "the Worker schedules license email delivery through Resend",
"then": [
"sendLicenseEmail posts the expected Resend payload with the full key and activation instructions",
"transient Resend failures retry with exponential backoff and typed failure after exhaustion",
"4xx Resend responses fail fast without retry",
"webhook handlers use ctx.waitUntil so email failure does not roll back D1 license persistence",
"email failure logs include the license id but not the raw email"
],
"evidence_required": [
"workers/test/email.test.ts red/green output",
"webhook failure-isolation vitest output",
"Worker typecheck output",
"blocked Resend test-mode integration logged because RESEND_API_KEY is absent"
]
}
19 changes: 19 additions & 0 deletions .atlas-ai/cdd/task-7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"task": 7,
"given": "A client asks the Worker to silently refresh an Atlas Pro license key by lid",
"when": "POST /license/refresh receives invalid JSON, unknown lids, cancelled subscriptions, active subscriptions, CORS preflight, or repeated requests",
"then": [
"invalid JSON or missing lid returns 400",
"unknown licenses return 403 with reason license_not_found",
"active or trialing Stripe subscriptions return a fresh signed key with continuity of lid, sub, and plan",
"cancelled D1 rows or inactive Stripe subscriptions return 403 with reason subscription_cancelled",
"per-lid D1 rate limiting allows 10 requests per UTC day and rejects the 11th with 429",
"CORS responses allow https://atlas-ai.au"
],
"evidence_required": [
"workers/test/refresh.test.ts red/green output",
"D1 migration 0002 applied locally",
"Worker typecheck and vitest output",
"blocked seeded live Stripe integration logged because Stripe credentials are absent"
]
}
16 changes: 16 additions & 0 deletions .atlas-ai/cdd/task-8.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"task": 8,
"given": "A saved Atlas Pro license is active or in grace and may be near expiry",
"when": "capability detection runs and the license is within the refresh window while telemetry is not opted out",
"then": [
"the client decides refresh eligibility without network access",
"the client POSTs only the license id to the refresh endpoint with a 5s timeout",
"a refreshed key is saved only after the full existing signature verification path accepts it",
"403, timeout, offline, and refresh exceptions never break capability detection"
],
"evidence_required": [
"python3 -m pytest tests/core/test_license_refresh.py -q",
"python3 -m pytest tests/core/test_capabilities.py tests/core/test_license_refresh.py -q",
"python3 -m pytest tests/ -q"
]
}
15 changes: 15 additions & 0 deletions .atlas-ai/cdd/task-9.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"task": 9,
"given": "Atlas Pro checkout is hosted outside this repository on atlas-ai.au and depends on Stripe dashboard state",
"when": "this repo documents the checkout surface contract",
"then": [
"the repo records the monthly and annual Atlas Pro price points",
"the repo records the externally hosted /pro and /pro/success URL contract",
"external Stripe product creation, live checkout wiring, webhook evidence, and site deployment are logged as blocked rather than fabricated"
],
"evidence_required": [
"grep -n \"Atlas Pro checkout contract\" README.md",
"python3 -m pytest tests/ -x -q",
"FLEET-LOG-NET.md BLOCKED entries for external Stripe/site subtasks"
]
}
1 change: 1 addition & 0 deletions .claude-plugin/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
marketplace.json
16 changes: 16 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "atlas-prd-taskmaster-local",
"description": "Local-path marketplace for prd-taskmaster plugin testing (v5.0.2 dev). Single plugin pointing to this worktree.",
"owner": {
"name": "Atlas-X-AI"
},
"plugins": [
{
"name": "prd-taskmaster",
"description": "Zero-config goal-to-tasks engine for Claude Code, plugin-native rebuild with CDD-verified execution",
"source": "./",
"category": "development"
}
]
}
13 changes: 13 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "prd-taskmaster",
"version": "4.0.0",
"description": "Zero-config goal-to-tasks engine for Claude Code (the Atlas engine). Graded PRD validation, dependency-ordered task graph, and CDD-verified execution.",
"author": {
"name": "Atlas AI",
"url": "https://atlas-ai.au"
},
"homepage": "https://github.com/anombyte93/prd-taskmaster",
"repository": "https://github.com/anombyte93/prd-taskmaster.git",
"license": "MIT",
"keywords": ["claude-code", "taskmaster", "prd", "plugin", "cdd", "atlas"]
}
108 changes: 108 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: tests

on:
push:
branches: [main]
pull_request:

jobs:
# Proves the zero-dependency promise: the package + CLI must run with NO pip
# installs at all (only the Python stdlib). Skill users install via curl and
# get exactly this.
stdlib-only:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Guard — package imports with no third-party deps
run: |
python -S -c "import sys; sys.path.insert(0,'.'); import prd_taskmaster, prd_taskmaster.cli, prd_taskmaster.pipeline, prd_taskmaster.shipcheck; print('stdlib-only import OK', prd_taskmaster.__version__)"
- name: Guard — no third-party imports anywhere in the package
run: |
python - <<'PY'
import ast, pathlib, sys
STDLIB = set(sys.stdlib_module_names)
allowed = STDLIB | {"prd_taskmaster"}
bad = []
for f in pathlib.Path("prd_taskmaster").rglob("*.py"):
tree = ast.parse(f.read_text())
for node in ast.walk(tree):
if isinstance(node, ast.Import):
mods = [n.name.split(".")[0] for n in node.names]
elif isinstance(node, ast.ImportFrom):
mods = [(node.module or "").split(".")[0]] if node.level == 0 else []
else:
continue
for m in mods:
if m and m not in allowed:
bad.append(f"{f}: {m}")
if bad:
print("Non-stdlib imports found:"); print("\n".join(bad)); sys.exit(1)
print("no third-party imports in prd_taskmaster/")
PY
- name: Install pytest only (no project deps)
run: pip install pytest
- name: Core + plugin tests (stdlib path)
run: python -m pytest tests/core tests/plugin -q

# Full suite including the FastMCP plugin surface (needs the mcp package).
full:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install deps
run: |
pip install pytest
pip install -r mcp-server/requirements.txt
- name: Full test suite
run: python -m pytest tests/ -q

quickstart-walkthrough:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Deterministic quickstart walkthrough
run: bash tests/scripts/quickstart-walkthrough.sh

# All five version strings must agree.
version-agreement:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Check version strings match
run: |
python - <<'PY'
import json, re, pathlib, sys
pkg = pathlib.Path("prd_taskmaster/__init__.py").read_text()
pkg_v = re.search(r'__version__\s*=\s*["\']([^"\']+)["\']', pkg).group(1)
pj = json.loads(pathlib.Path("package.json").read_text())["version"]
plug = json.loads(pathlib.Path(".claude-plugin/plugin.json").read_text())["version"]
sh = re.search(r'VERSION="([^"]+)"', pathlib.Path("install.sh").read_text()).group(1)
chlog = pathlib.Path("CHANGELOG.md").read_text()
chlog_has = "v4.0.0" in chlog or "[4.0.0]" in chlog or "4.0.0" in chlog
versions = {"package/__init__": pkg_v, "package.json": pj, "plugin.json": plug, "install.sh": sh}
print(versions, "CHANGELOG mentions 4.0.0:", chlog_has)
vals = set(versions.values())
if len(vals) != 1:
print("VERSION MISMATCH:", versions); sys.exit(1)
if not chlog_has:
print("CHANGELOG missing the current version entry"); sys.exit(1)
print("all versions agree:", vals.pop())
PY
35 changes: 35 additions & 0 deletions .github/workflows/worker-secret-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Worker secret scan

on:
pull_request:
paths:
- "workers/**"
- "scripts/deploy-worker.sh"
- ".github/workflows/worker-secret-scan.yml"
push:
branches:
- fleet-w2-backend
paths:
- "workers/**"
- "scripts/deploy-worker.sh"
- ".github/workflows/worker-secret-scan.yml"

jobs:
worker-secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Scan Worker files for committed secrets
run: |
set -euo pipefail
stripe_key='sk_(live|test)_'
stripe_webhook='wh''sec_[A-Za-z0-9]+'
resend_key='re_[A-Za-z0-9]{20,}'
pem_key='-----BEGIN [A-Z ]*PRIVATE KEY-----'
ed_key='ED25519_PRIVATE_KEY=[0-9a-fA-F]{64}'
secret_pattern="(${stripe_key}|${stripe_webhook}|${resend_key}|${pem_key}|${ed_key})"
if git ls-files workers scripts/deploy-worker.sh .github/workflows/worker-secret-scan.yml \
| xargs grep -nE "${secret_pattern}"; then
echo "Potential Worker secret material was committed." >&2
exit 1
fi
Loading
Loading