Skip to content
Closed
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
64 changes: 64 additions & 0 deletions .githooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# .githooks/commit-msg
# Repo-managed commit-msg hook: checks commit message against local denylist.
# Install: bash scripts/setup-hooks.sh (or: git config core.hooksPath .githooks)
#
# Reads patterns from reference/guard-denylist.txt (local-only, gitignored).
# Also checks for objective issues (internal markers, hidden Unicode).
#
# Bypass: PEAC_SKIP_COMMIT_MSG=1 git commit -m "..."

set -euo pipefail

COMMIT_MSG_FILE="$1"

if [ "${PEAC_SKIP_COMMIT_MSG:-}" = "1" ]; then
echo "[commit-msg] BYPASSED (PEAC_SKIP_COMMIT_MSG=1)"
echo "[commit-msg] WARNING: Commit message was not checked for non-technical language."
exit 0
fi

REPO_ROOT="$(git rev-parse --show-toplevel)"
DENYLIST="$REPO_ROOT/reference/guard-denylist.txt"
FAILED=0

# Built-in checks (always active, safe for tracked script)
if grep -iE 'reference/.*_LOCAL\.' "$COMMIT_MSG_FILE" >/dev/null 2>&1; then
echo "[commit-msg] FAIL: Commit message references local-only files"
FAILED=1
fi

if grep -q 'x403' "$COMMIT_MSG_FILE" >/dev/null 2>&1; then
echo "[commit-msg] FAIL: Commit message contains x403 typo"
FAILED=1
fi

if grep -iE '(NEXT_STEPS|ROADMAP_LOCAL|STRATEGY_LOCAL|SCOPE_LEDGER|MASTER_PLAN_LOCAL)' "$COMMIT_MSG_FILE" >/dev/null 2>&1; then
echo "[commit-msg] FAIL: Commit message contains internal planning markers"
FAILED=1
fi

# Local denylist check (if denylist exists)
if [ -f "$DENYLIST" ]; then
while IFS= read -r line || [ -n "$line" ]; do
# Skip comments and blank lines
trimmed=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -z "$trimmed" ] && continue
echo "$trimmed" | grep -q '^#' && continue

if grep -iE "$trimmed" "$COMMIT_MSG_FILE" >/dev/null 2>&1; then
echo "[commit-msg] FAIL: Commit message matches denylist pattern: $trimmed"
FAILED=1
fi
done < "$DENYLIST"
fi

if [ "$FAILED" -eq 1 ]; then
echo ""
echo "[commit-msg] Commit message contains non-technical language."
echo "[commit-msg] Rewrite the message to be technical and implementation-focused."
echo "[commit-msg] Bypass: PEAC_SKIP_COMMIT_MSG=1 git commit ..."
exit 1
fi

echo "[commit-msg] OK"
7 changes: 5 additions & 2 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ if git diff --cached --name-only | grep -q 'specs/kernel/errors.json'; then
echo "[pre-commit] errors.generated.ts updated and staged"
fi

echo "[pre-commit] Checking for planning leaks..."
bash scripts/check-planning-leak.sh
# Planning leak check (local-only script; skipped on fresh clones)
if [ -f scripts/check-planning-leak.sh ]; then
echo "[pre-commit] Checking for planning leaks..."
bash scripts/check-planning-leak.sh
fi

echo "[pre-commit] OK"
47 changes: 17 additions & 30 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
## Summary

<!-- Brief description of what this PR does -->
<!-- Technical summary of what this PR changes. Keep factual and implementation-focused. -->

## Type of Change
## Scope

- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] Refactoring (no functional changes)
- [ ] CI/Build changes

## Related Issues

<!-- Link to related issues, e.g., Fixes #123 -->
<!-- What this PR changes and what it does not change. -->

## Changes

Expand All @@ -23,28 +14,24 @@
-
-

## Testing
## Test plan

<!-- Describe how you tested these changes -->
<!-- How these changes were verified -->

- [ ] Unit tests pass (`pnpm test`)
- [ ] Lint passes (`pnpm run lint`)
- [ ] Type check passes (`pnpm run typecheck`)
- [ ] Manual testing performed
- [ ] `pnpm test` passes
- [ ] `pnpm lint` passes
- [ ] `pnpm typecheck:core` passes
- [ ] `bash scripts/guard.sh` passes

## Checklist

- [ ] My code follows the project's coding standards
- [ ] I have updated documentation as needed
- [ ] I have added tests for new functionality
- [ ] All existing tests pass
- [ ] My commit messages follow conventional commits format
- [ ] I have checked for breaking changes and documented them

## Breaking Changes

<!-- If this is a breaking change, describe the impact and migration path -->
- [ ] Code follows project coding standards
- [ ] Documentation updated as needed
- [ ] Tests added for new functionality
- [ ] Commit messages use conventional format
- [ ] PR title is technical and under 70 chars
- [ ] PR body contains only technical content (no internal planning, sequencing, or process language)

## Additional Notes
## Follow-ups

<!-- Any additional context or screenshots -->
<!-- Technical follow-ups only. Leave empty if none. -->
57 changes: 57 additions & 0 deletions .github/workflows/pr-metadata-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: PR Metadata Lint

on:
pull_request:
types: [opened, edited, synchronize]

jobs:
lint-metadata:
name: Check PR title and body
runs-on: ubuntu-latest
timeout-minutes: 2

steps:
- name: Lint PR metadata
env:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
run: |
FAILED=0

# Write PR content to temp files for safe grep
printf '%s' "$PR_TITLE" > /tmp/pr-title.txt
printf '%s' "$PR_BODY" > /tmp/pr-body.txt

# Check for reference path leaks (local-only file references)
if grep -iE 'reference/.*_LOCAL\.' /tmp/pr-title.txt /tmp/pr-body.txt 2>/dev/null; then
echo "::error::PR metadata contains reference to local-only files"
FAILED=1
fi

# Check for x403 typo
if grep -q 'x403' /tmp/pr-title.txt /tmp/pr-body.txt 2>/dev/null; then
echo "::error::PR metadata contains x403 typo (should be x402)"
FAILED=1
fi

# Check for internal planning markers
if grep -iE '(NEXT_STEPS|ROADMAP_LOCAL|STRATEGY_LOCAL|SCOPE_LEDGER|MASTER_PLAN_LOCAL|MEMORY\.md)' /tmp/pr-title.txt /tmp/pr-body.txt 2>/dev/null; then
echo "::error::PR metadata contains internal planning markers"
FAILED=1
fi

# Check for hidden/bidirectional Unicode
if grep -P '[\x{200B}-\x{200F}\x{2028}-\x{202F}\x{2060}-\x{206F}\x{FEFF}]' /tmp/pr-title.txt /tmp/pr-body.txt 2>/dev/null; then
echo "::error::PR metadata contains hidden or bidirectional Unicode characters"
FAILED=1
fi

rm -f /tmp/pr-title.txt /tmp/pr-body.txt

if [ "$FAILED" -eq 1 ]; then
echo ""
echo "PR metadata lint failed. Remove non-technical language from PR title/body."
exit 1
fi

echo "PR metadata lint: OK"
105 changes: 105 additions & 0 deletions docs/VERIFY-RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Verifying a PEAC Release

This document describes independent methods for verifying the integrity and provenance of a PEAC Protocol release. Each method addresses a different layer of the supply chain.

## 1. Gate Report (Authoritative Evidence)

Each release includes a machine-generated gate report that records every quality gate result. For stable releases, this includes all DD-90 gates.

```bash
# Generate the authoritative gate report (writes JSON artifact)
bash scripts/release/run-gates.sh --target stable --write-release-artifacts

# Dry-run only (no artifacts, no release claim)
bash scripts/release/run-gates.sh --target stable
```

The `--write-release-artifacts` flag is the authoritative gate path. Without it, the script is a local dry-run that never claims "ready to tag." The JSON artifact at `docs/releases/<version>-gate-report.json` includes: timestamp, commit SHA, Node version, runner metadata, publish-manifest hash, conformance-fixtures hash, and individual gate pass/fail status with duration.

## 2. npm Provenance

PEAC packages published via GitHub Actions OIDC include npm provenance attestations. This cryptographically links each package version to the specific workflow run that produced it.

**Current state (v0.12.0-preview.2):** 9 of 28 publishable packages are configured for OIDC trusted publishing. The remaining 19 are pending migration via `npm trust` CLI (tracked in PR 6a). All packages published through the CI workflow receive `--provenance` attestations regardless of OIDC status.

```bash
# Verify provenance for published packages
# Use a temp project to avoid workspace interference:
mkdir /tmp/peac-verify && cd /tmp/peac-verify
npm init -y
npm install @peac/protocol@next
npm audit signatures
cd - && rm -rf /tmp/peac-verify
```

The provenance attestation confirms:

- The package was built from the declared source repository
- The build ran in a GitHub Actions environment
- No human had direct access to the npm publish token

**Note:** `npm audit signatures` must be run in a project that has installed the packages. Running it with a bare package name does not work.

## 3. Conformance Matrix

The conformance matrix traces every normative requirement (BCP 14 statements) to test coverage.

```bash
# Verify conformance tooling
node scripts/conformance/validate-schemas.mjs
node scripts/conformance/verify-registry-drift.mjs
node scripts/conformance/generate-inventory.mjs --check
```

Artifacts:

- `specs/conformance/requirement-ids.json`: machine-readable requirement registry (146 IDs)
- `docs/specs/CONFORMANCE-MATRIX.md`: generated coverage matrix
- `specs/conformance/fixtures/inventory.json`: fixture inventory with requirement mappings

## 4. API Surface Snapshots

Public API exports are snapshot-locked. Any unreviewed change to the public API surface causes the gate to fail.

```bash
# Verify API surface matches committed snapshots
bash scripts/release/api-surface-lock.sh
```

Snapshots are stored in `scripts/release/api-snapshots/` and cover the primary packages (`kernel`, `schema`, `crypto`, `protocol`, `control`, `mcp-server`, `middleware-core`, `middleware-express`, `sdk-js`).

## 5. Pack-Install Smoke

Representative packages are packed into tarballs, installed in isolated temp directories, and verified for ESM import, CJS require, TypeScript types resolution, and CLI bin execution.

```bash
# Run the pack-install smoke test
bash scripts/release/pack-install-smoke.sh
```

This catches packaging errors that unit tests cannot detect: missing files in the `files` array, broken exports maps, missing bin entries, and CJS/ESM resolution failures.

## 6. Attestations and SBOM (Pending)

The following verification methods are planned but not yet implemented:

- **Sigstore attestations:** Per-package Sigstore attestation bundles (pending PR 6a: OIDC migration)
- **SBOM generation:** CycloneDX or SPDX SBOM for each published package (pending tooling evaluation)
- **Checksum manifest:** SHA-256 checksums for all published tarballs (pending release automation)

These will be added as part of the publisher-trust work tracked in the stable release plan.

## Verification Checklist

For a stable release, all of these should pass:

```bash
# Full authoritative gate suite
bash scripts/release/run-gates.sh --target stable --write-release-artifacts

# Individual checks
bash scripts/release/api-surface-lock.sh
bash scripts/release/pack-install-smoke.sh
node scripts/conformance/verify-registry-drift.mjs
node scripts/conformance/generate-inventory.mjs --check
```
30 changes: 30 additions & 0 deletions docs/adoption/confirmations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# External Integration Confirmations

> **Purpose:** DD-90 stable gate requires at least one external confirmation meeting the quality bar below.
> **Gate:** `run-gates.sh --target stable` checks this file has >= 1 valid entry.

## Quality Bar (6 Required Fields)

Each confirmation entry MUST include all 6 fields:

1. **Team/Project:** Name of the team or project
2. **Integration Surface:** Which PEAC integration point is used (e.g., MCP receipts, A2A metadata carrier, HTTP header)
3. **Integration Impact:** One sentence describing what this integration enables or replaces
4. **Date:** ISO 8601 date of confirmation
5. **Public Link:** URL to public evidence (PR, blog post, repo, or issue); "private" if under NDA (requires maintainer attestation)
6. **Contact Role:** Role of the confirming contact (e.g., "Engineering Lead", "CTO"); no PII

## Confirmations

<!-- Add entries below. Each entry must have all 6 fields. -->
<!-- Example:
### Acme Agent Platform
- **Team/Project:** Acme Agent Platform
- **Integration Surface:** MCP receipt issuance via `peac_issue` tool
- **Integration Impact:** Replaced custom audit log with structured receipts, reducing compliance integration time.
- **Date:** 2026-04-01
- **Public Link:** https://github.com/acme/agent-platform/pull/42
- **Contact Role:** Engineering Lead
-->

_No external confirmations recorded._
56 changes: 56 additions & 0 deletions docs/adoption/integration-evidence.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"$schema": "./integration-evidence.schema.json",
"$comment": "Canonical source for DD-90 integration evidence. docs/adoption/integration-evidence.md is generated from this file.",
"version": "1.0.0",
"integrations": [
{
"ecosystem": "MCP",
"full_name": "Model Context Protocol",
"pr": 472,
"pr_commit": "9e5c5dea",
"dd90_gate": true,
"surface": "peac_issue tool produces Wire 0.2 receipts; peac_verify tool verifies them",
"evidence": "Round-trip issuance and verification via MCP tool calls",
"wire_version": "0.2",
"test_files": [
"packages/mcp-server/tests/handlers/issue.test.ts",
"packages/mcp-server/tests/handlers/verify.test.ts"
],
"spec_refs": ["docs/specs/EVIDENCE-CARRIER-CONTRACT.md"]
},
{
"ecosystem": "A2A",
"full_name": "Agent-to-Agent Protocol",
"pr": 473,
"pr_commit": "56fd7047",
"dd90_gate": true,
"surface": "Wire 0.2 receipts carried in A2A metadata[extensionURI] per Evidence Carrier Contract",
"evidence": "Round-trip through A2A metadata carrier (issue, embed, extract, verify)",
"wire_version": "0.2",
"test_files": ["tests/integration/a2a/wire02-roundtrip.test.ts"],
"spec_refs": ["docs/specs/EVIDENCE-CARRIER-CONTRACT.md"]
},
{
"ecosystem": "EAT",
"full_name": "Entity Attestation Token",
"pr": 474,
"pr_commit": "f20e0f61",
"dd90_gate": false,
"dd_reference": "DD-154",
"surface": "COSE_Sign1 (RFC 9052) identity adapter; maps EAT claims to PEAC actor binding",
"evidence": "Passport-style identity input; does not produce Wire 0.2 receipts in the EAT ecosystem",
"wire_version": null,
"rationale": "EAT is an identity input surface. It enriches PEAC receipts with external attestations but does not constitute a distinct ecosystem producing Wire 0.2 evidence.",
"test_files": [
"packages/adapters/eat/tests/passport.test.ts",
"packages/adapters/eat/tests/claim-mapper.test.ts"
],
"spec_refs": ["docs/specs/EVIDENCE-CARRIER-CONTRACT.md"]
}
],
"classification_rules": [
"An integration counts toward DD-90 if it produces or consumes Wire 0.2 receipts (interaction-record+jwt) in a distinct protocol ecosystem.",
"Identity adapters, claim mappers, and format converters that feed into PEAC but do not themselves produce receipts are classified under their own DDs.",
"Do not inflate the ecosystem count by reclassifying adapters as integrations."
]
}
Loading
Loading