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
39 changes: 39 additions & 0 deletions .github/ISSUE_TEMPLATE/quickstart-feedback.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Quickstart feedback
description: Report friction from the first TTP demo or integration path.
title: "[Quickstart]: "
labels:
- docs
- developer-experience
body:
- type: markdown
attributes:
value: |
Use this when the local demo, getting started guide, or first integration path is unclear or does not work.
- type: input
id: path
attributes:
label: Path tried
description: Which path were you using?
placeholder: npm run demo, SDK install, Trust Authority setup, GitHub Actions gate
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected outcome
description: What did you expect to happen?
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual outcome
description: What happened instead? Include command output if useful.
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
description: Node version, OS, package manager, and any relevant runtime context.
placeholder: Node 20, macOS/Linux/Windows, npm/pnpm/yarn
106 changes: 12 additions & 94 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,106 +1,24 @@
name: CI / Repository Health
name: CI

on:
push:
branches: ["**"]
pull_request:
push:
branches:
- main

jobs:
test:
name: Test and Smoke Checks
verify:
name: Demo and Tests
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Run test suite
run: npm test

- name: Compile Python SDK
run: python -m py_compile sdk/python/client.py

- name: SDK + gate smoke matrix
shell: bash
run: |
set -euo pipefail

node reference-implementations/runtime-authority-gate/server.mjs >/tmp/runtime-gate.log 2>&1 &
GATE_PID=$!
trap 'kill $GATE_PID' EXIT

for i in {1..20}; do
if curl -fsS http://127.0.0.1:8080/healthz >/dev/null; then
break
fi
sleep 0.2
done

# PERMIT
curl -fsS -X POST http://127.0.0.1:8080/re/authorize \
-H 'content-type: application/json' \
-d '{"requestId":"ci-permit","subject":"ci-agent","action":"pipeline.deploy","resource":{"id":"prod"},"context":{"trustScore":0.9,"environment":"dev"},"authorityGrant":{"grantId":"grant-local-001"}}' \
| jq -e '.decision=="PERMIT" and .mode=="FULL" and .rapDecision=="allow"' >/dev/null

# STEP_UP
STEP_UP_RECEIPT=$(curl -fsS -X POST http://127.0.0.1:8080/re/authorize \
-H 'content-type: application/json' \
-d '{"requestId":"ci-stepup","subject":"ci-agent","action":"pipeline.deploy","resource":{"id":"prod"},"context":{"trustScore":0.55,"environment":"dev"},"authorityGrant":{"grantId":"grant-local-001"}}' \
| jq -r 'select(.decision=="STEP_UP" and .rapDecision=="step_up") | .receiptId')
test -n "$STEP_UP_RECEIPT"

# ESCALATE
curl -fsS -X POST http://127.0.0.1:8080/re/authorize \
-H 'content-type: application/json' \
-d '{"requestId":"ci-escalate","subject":"mythos-agent","action":"tool.invoke.delete_secret","resource":{"id":"prod-secret"},"context":{"trustScore":0.95,"environment":"prod","agentType":"mythos"},"authorityGrant":{"grantId":"grant-local-001"}}' \
| jq -e '.decision=="ESCALATE" and .rapDecision=="escalate"' >/dev/null

# DENY
curl -fsS -X POST http://127.0.0.1:8080/re/authorize \
-H 'content-type: application/json' \
-d '{"requestId":"ci-deny","subject":"ci-agent","action":"pipeline.deploy","resource":{"id":"prod"},"context":{"trustScore":0.1,"environment":"dev"},"authorityGrant":{"grantId":"grant-local-001"}}' \
| jq -e '.decision=="DENY" and .rapDecision=="deny"' >/dev/null

# REAUTHORIZE
curl -fsS -X POST http://127.0.0.1:8080/re/reauthorize \
-H 'content-type: application/json' \
-d "{\"requestId\":\"ci-reauth\",\"priorReceiptId\":\"$STEP_UP_RECEIPT\",\"approval\":{\"approvedBy\":\"ops-admin\",\"evidenceRef\":\"ticket-ci\"}}" \
| jq -e '.decision=="PERMIT" and .mode=="CONSTRAINED" and .rapDecision=="throttle"' >/dev/null
node-version: 20

python - <<'PY'
from sdk.python import authorize, AuthorizeRequest, Principal, Resource, AuthorityGrant
resp = authorize(AuthorizeRequest(
base_url='http://127.0.0.1:8080',
requestId='ci-py-1',
principal=Principal(id='py-ci-agent', type='service-agent'),
action='pipeline.deploy',
resource=Resource(type='environment', id='prod'),
context={'trustScore': 0.91, 'environment': 'dev'},
authorityGrant=AuthorityGrant(grantId='grant-local-001', expiresAt='2030-01-01T00:00:00Z', scope=['pipeline.deploy:prod'])
))
assert resp.decision.value == 'PERMIT'
PY
- name: Run local adoption demo
run: npm run demo

node --input-type=module - <<'JS'
import { authorize } from './sdk/node/index.js';
const resp = await authorize({
baseUrl: 'http://127.0.0.1:8080',
requestId: 'ci-node-1',
principal: { id: 'node-ci-agent', type: 'service-agent' },
action: 'pipeline.deploy',
resource: { type: 'environment', id: 'prod' },
context: { trustScore: 0.92, environment: 'dev' },
authorityGrant: {
grantId: 'grant-local-001',
expiresAt: '2030-01-01T00:00:00Z',
scope: ['pipeline.deploy:prod']
}
});
if (resp.decision !== 'PERMIT') throw new Error('Expected PERMIT');
JS
- name: Run trust-routing tests
run: npm run test:trust-routing
131 changes: 131 additions & 0 deletions .github/workflows/governed-execution.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: TTP / Governed Execution Proof

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
Comment on lines +1 to +5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the duplicate governed workflow

This adds a second pull_request workflow with the same name and body as the already-present .github/workflows/governed_execution.yml (checked that file in the repo). With both files active, every PR runs the governed execution gate twice and calls the external /re/authorize service twice, which can leave contributors with duplicate checks to satisfy and duplicate authorization side effects; delete one copy or replace the existing file instead of adding another.

Useful? React with 👍 / 👎.


jobs:
govern:
name: Governed Execution
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write

outputs:
decision: ${{ steps.authorize.outputs.decision }}
receipt: ${{ steps.authorize.outputs.receipt }}

steps:
# 1️⃣ Full checkout (safe and correct)
- uses: actions/checkout@v4
with:
fetch-depth: 0

# 2️⃣ Detect changed files
- name: Detect changes
id: changes
shell: bash
run: |
set -euo pipefail
BASE="${{ github.event.pull_request.base.sha }}"
HEAD="${{ github.event.pull_request.head.sha }}"

git diff --name-only "$BASE" "$HEAD" > changed.txt || true

echo "Changed files:"
cat changed.txt || true

PATHS_JSON=$(jq -R . < changed.txt | jq -s .)
echo "paths=$PATHS_JSON" >> "$GITHUB_OUTPUT"

# 3️⃣ Ask external authority for permission
- name: Authorize execution
id: authorize
env:
AUTH_URL: ${{ secrets.RUNTIME_AUTH_URL }}
AUTH_TOKEN: ${{ secrets.RUNTIME_AUTH_TOKEN }}
shell: bash
run: |
set -euo pipefail

if [ ! -s changed.txt ]; then
echo "No changes → deny by policy"
echo "decision=DENY" >> "$GITHUB_OUTPUT"
echo "receipt=" >> "$GITHUB_OUTPUT"
exit 0
fi

jq -n \
--arg repo "${{ github.repository }}" \
--arg actor "${{ github.actor }}" \
--arg pr "${{ github.event.pull_request.number }}" \
--arg sha "${{ github.event.pull_request.head.sha }}" \
--argjson paths "$(jq -s . changed.txt | jq -R .)" \
'{
subject: "wi://github/actions/runner",
action: "pull_request.execute",
resource: ("repo:" + $repo + ":pr/" + $pr),
commitSha: $sha,
actor: $actor,
pathsTouched: $paths,
context: {
event: "pull_request",
repo: $repo
}
}' > request.json

curl -sS \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-X POST "$AUTH_URL/re/authorize" \
-d @request.json \
> response.json

cat response.json

DECISION=$(jq -r '.decision // "DENY"' response.json)
RECEIPT=$(jq -r '.receiptId // ""' response.json)

echo "decision=$DECISION" >> "$GITHUB_OUTPUT"
echo "receipt=$RECEIPT" >> "$GITHUB_OUTPUT"

# 4️⃣ Human approval if required
step-up:
name: Step‑Up Approval
runs-on: ubuntu-latest
needs: govern
if: needs.govern.outputs.decision == 'STEP_UP'
environment:
name: protected-execution
steps:
- run: |
echo "Manual authorization granted via environment."
echo "Receipt: ${{ needs.govern.outputs.receipt }}"

# 5️⃣ Final enforcement gate
enforce:
name: Enforce Authority Decision
runs-on: ubuntu-latest
needs: [govern, step-up]
if: always()
steps:
- run: |
DECISION="${{ needs.govern.outputs.decision }}"
RECEIPT="${{ needs.govern.outputs.receipt }}"

echo "Final decision: $DECISION"
echo "Receipt: $RECEIPT"

if [ -z "$RECEIPT" ]; then
echo "Missing receipt → hard deny"
exit 1
fi

if [ "$DECISION" = "PERMIT" ]; then
echo "✅ Execution permitted"
exit 0
fi

echo "❌ Execution denied"
exit 1
Loading
Loading