Governance
The governance model for the Bastion Security Framework, implemented entirely with GitHub-native features.
Principles
- All changes via PR — no direct pushes to
main, ever - N-of-M approval — critical changes require multiple designated reviewers
- Path-scoped ownership — different directories have different review requirements
- Auditable rights transfer — adding/removing reviewers is tracked and requires approval
- Self-protecting governance — changing the governance rules requires governance approval
- Zero third-party dependencies — only GitHub-native features
Roles
Security Board
The primary governance body. Members have authority to approve changes to security-critical content: vectors, semgrep rules, standards, and agents.
- Size: 5 members (configurable)
- Quorum: 3 of 5 must approve (configurable per path)
- GitHub mechanism:
@org/security-boardteam - Responsibilities:
- Review and vote on community vector proposals
- Approve changes to semgrep rules
- Approve changes to standards mappings
- Approve changes to agent definitions
- Approve governance changes (CODEOWNERS, rulesets)
Agent Maintainers
Responsible for the AI agent definitions and intelligence pipeline.
- GitHub mechanism:
@org/agent-maintainers - Scope:
agents/,intel/,skills/ - Note: Changes to agent files also require security board approval (dual ownership)
Tooling Maintainers
Responsible for scripts, MCP server, and build tooling.
- GitHub mechanism:
@org/tooling-team - Scope:
scripts/,mcp-server/,make/,schema/
Contributors
Anyone can submit a proposal. Contributors don't need org membership — they fork the repo and submit a PR.
GitHub Configuration
Step 1: Create GitHub Teams
In your GitHub organization settings:
Organization → Teams → New team
Team 1: security-board
Description: "Bastion Security Board — approves vectors, rules, and governance changes"
Visibility: Visible
Members: [alice, bob, carol, dave, eve]
Permission: Write access to daml-security-framework repo
Team 2: agent-maintainers
Description: "Bastion Agent Maintainers — maintains AI agent definitions"
Visibility: Visible
Members: [alice, frank]
Permission: Write access to daml-security-framework repo
Team 3: tooling-team
Description: "Bastion Tooling — maintains scripts, MCP server, build system"
Visibility: Visible
Members: [bob, grace]
Permission: Write access to daml-security-framework repo
Step 2: Create CODEOWNERS
Create .github/CODEOWNERS:
# =============================================================================
# Bastion CODEOWNERS — Defines who is automatically requested for review
# Changes to this file require security board approval (self-protecting)
# =============================================================================
# Governance files — security board owns governance
.github/CODEOWNERS @org/security-board
.github/FUNDING.yml @org/security-board
.github/workflows/ @org/security-board
# Security-critical content — security board must review
/vectors/ @org/security-board
/semgrep/ @org/security-board
/standards/ @org/security-board
/intel/ @org/security-board
# Agent definitions — dual ownership (agent maintainers + security board)
/agents/ @org/security-board @org/agent-maintainers
# Skills — dual ownership
/skills/ @org/security-board @org/agent-maintainers
# Tooling — tooling team (security board consulted for security-impacting changes)
/scripts/ @org/tooling-team
/mcp-server/ @org/tooling-team
/make/ @org/tooling-team
/schema/ @org/tooling-team
# Framework config
/registry.yaml @org/security-board
/bastion.yaml.example @org/tooling-team
CLAUDE.md @org/security-board
# Documentation
/docs/ARCHITECTURE.md @org/security-board
/docs/GOVERNANCE.md @org/security-board
README.md @org/security-board
Step 3: Configure Branch Protection on main
Repository Settings → Branches → Add rule for main:
- Require a pull request before merging
- Require approvals: 1 (minimum — rulesets handle the N-of-M)
- Dismiss stale pull request approvals when new commits are pushed
- Require review from Code Owners
- Require status checks to pass before merging
- Required checks:
schema-validation,governance-check(added in Step 5)
- Required checks:
- Require linear history
- Do not allow bypassing the above settings
- Include administrators
- Restrict who can push to matching branches
- Only:
@org/security-board
- Only:
Step 4: Configure Rulesets
Repository Settings → Rules → Rulesets → New branch ruleset:
Ruleset 1: Security Content (vectors, rules, standards)
Name: security-content-review
Enforcement: Active
Target: main branch
Rules:
- Require pull request
- Required approvals: 3
- Dismiss stale reviews: Yes
- Require review from specific team:
Team: @org/security-board
Required approvals: 3
File patterns:
- vectors/**
- semgrep/**
- standards/**
- intel/**
- registry.yaml
- Require status checks:
- schema-validation
- duplicate-check
Bypass list: (empty — no one bypasses)
Ruleset 2: Agent and Skills Changes
Name: agent-review
Enforcement: Active
Target: main branch
Rules:
- Require pull request
- Required approvals: 2
- Require review from specific team:
Team: @org/security-board
Required approvals: 1
File patterns:
- agents/**
- skills/**
- Require review from specific team:
Team: @org/agent-maintainers
Required approvals: 1
File patterns:
- agents/**
- skills/**
Bypass list: (empty)
Ruleset 3: Governance Changes (highest bar)
Name: governance-review
Enforcement: Active
Target: main branch
Rules:
- Require pull request
- Required approvals: 4
- Require review from specific team:
Team: @org/security-board
Required approvals: 4
File patterns:
- .github/CODEOWNERS
- .github/workflows/governance*.yml
- docs/GOVERNANCE.md
Bypass list: (empty — governance changes require near-unanimity)
Ruleset 4: Tooling Changes
Name: tooling-review
Enforcement: Active
Target: main branch
Rules:
- Require pull request
- Required approvals: 1
- Require review from specific team:
Team: @org/tooling-team
Required approvals: 1
File patterns:
- scripts/**
- mcp-server/**
- make/**
- schema/**
Bypass list: (empty)
Step 5: GitHub Actions (Validation Only)
These actions validate PR content — they do NOT enforce approval logic (rulesets handle that).
.github/workflows/validate-proposal.yml
name: Validate Proposal
on:
pull_request:
paths:
- 'vectors/**'
- 'semgrep/**'
jobs:
schema-validation:
name: schema-validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: pip install pyyaml
- name: Validate vector YAML schema
run: python scripts/validate_schema.py
- name: Check for duplicate vector IDs
run: python scripts/check_duplicates.py
- name: Validate semgrep rules syntax
run: |
pip install semgrep
semgrep --validate --config semgrep/
duplicate-check:
name: duplicate-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for duplicate CWEs and vector names
run: python scripts/check_duplicates.py
.github/workflows/label-proposal.yml
name: Label Proposal PR
on:
pull_request:
paths:
- 'vectors/**'
jobs:
label:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Detect domain and severity
id: detect
run: |
# Parse the changed vector files to extract domain and severity
python scripts/detect_proposal_metadata.py >> "$GITHUB_OUTPUT"
- name: Apply labels
uses: actions/github-script@v7
with:
script: |
const domain = '${{ steps.detect.outputs.domain }}';
const severity = '${{ steps.detect.outputs.severity }}';
const labels = ['proposal', `domain:${domain}`, `severity:${severity}`];
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: labels
});
Step 6: PR Templates
.github/PULL_REQUEST_TEMPLATE/vector-proposal.md
## Vector Proposal
### Proposed Vector
- **Name:**
- **Domain:** authorization | arithmetic | temporal | state
- **Severity:** CRITICAL | HIGH | MEDIUM | LOW
- **CWE:**
### Evidence
<!-- How was this discovered? Link to external source, audit finding, or code review. -->
### Applicability
<!-- Does this apply to ANY DAML/Canton project, or only specific implementations? -->
### Mitigation Pattern
```daml
-- DAML code showing the fix
Test Evidence
Checklist
- Vector applies to generic DAML/Canton patterns (not project-specific)
- CWE classification verified
- Mitigation pattern is complete and DAML-idiomatic
- No project-specific file paths, names, or business logic
- Checked for duplicates against existing vectors
---
## Rights Transfer Protocol
### Adding a New Board Member
```mermaid
flowchart TD
A[Member opens nomination Issue] --> B[7-day discussion period]
B --> C[Org owner creates membership PR]
C --> D{3 of 5 board members approve?}
D -->|Approved| E[Member added to team]
D -->|Rejected| F[Issue closed with feedback]
E --> G[Logged in org audit log]
- A current security board member opens a GitHub Issue nominating a new member
- 7-day discussion period for the board to evaluate the candidate
- Org owner or team maintainer creates a team membership change
- 3 of 5 current board members must approve
- On approval, the new member is added to
@org/security-board - Change is logged in the GitHub org audit log with timestamp and actor
- New member immediately has approval authority on future PRs
Removing a Board Member
- A current board member opens a GitHub Issue proposing removal (with reason)
- 7-day discussion period
- 3 of 5 current board members must approve the removal
- Org owner removes the member from
@org/security-board - Authority is revoked immediately — pending reviews by this member no longer count
Emergency: Board Member Compromise
This is the only scenario where removal happens before board vote — compromise response must be immediate. The org owner acts unilaterally and notifies the board after the fact.
Approval Requirements Summary
| What changed | Who reviews | Approvals needed |
|---|---|---|
vectors/community/** | @org/security-board | 3 of 5 |
semgrep/** | @org/security-board | 3 of 5 |
standards/** | @org/security-board | 3 of 5 |
intel/** | @org/security-board | 3 of 5 |
agents/** | @org/security-board + @org/agent-maintainers | 1 from each |
skills/** | @org/security-board + @org/agent-maintainers | 1 from each |
scripts/**, mcp-server/** | @org/tooling-team | 1 |
.github/CODEOWNERS | @org/security-board | 4 of 5 |
docs/GOVERNANCE.md | @org/security-board | 4 of 5 |
registry.yaml | @org/security-board | 3 of 5 |
README.md, docs/* | @org/security-board | 1 |
Audit Trail
All governance events are tracked in GitHub's native audit log:
| Event | Where logged | Retention |
|---|---|---|
| PR created | Repository activity | Forever (git history) |
| PR approved/rejected | PR review history | Forever |
| PR merged | Git log + PR history | Forever |
| Team member added | Org audit log | 180 days (free/Team) |
| Team member removed | Org audit log | 180 days (free/Team) |
| Ruleset changed | Org audit log | 180 days |
| Branch protection changed | Org audit log | 180 days |
For longer retention of team membership changes, consider exporting the audit log periodically via the GitHub API (GET /orgs/{org}/audit-log).