TODO:
July 12, 2026 · View on GitHub
This is the project configuration for TODO: <project-name>.
Every skill under ../../.claude/skills/
reads the project name from <project-config>/project.md and then loads this manifest to resolve project-specific identity,
repositories, mailing lists, and references to the other files in
this directory.
Grep for TODO to see every field you still need to fill in:
grep -n TODO projects/<name>/project.md
Identity
| Key | Value |
|---|---|
organization | TODO: the organization whose defaults this project inherits — e.g. ASF (organizations/ASF/). Default independent (organizations/independent/). See organizations/README.md. |
project_name | TODO: e.g. Apache Foo |
vendor | TODO: e.g. Apache Software Foundation |
short_name | TODO: e.g. Foo |
product_family_url | TODO: e.g. https://foo.apache.org/ |
The vendor / project_name pair is what lands in the vendor and
product fields of the CVE 5.x record the CVE-JSON generator
produces.
Repositories
| Key | Value | Purpose |
|---|---|---|
tracker_repo | TODO: e.g. foo-s/foo-s | Private security tracker (this repo) |
tracker_repo_url | TODO | |
tracker_default_branch | TODO: e.g. main | Default PR target for the tracker repo |
tracker_project_board_url | TODO: URL of the GitHub Project V2 board, if any | Security board |
upstream_repo | TODO: e.g. apache/foo | Public codebase where fixes land |
upstream_repo_url | TODO | |
upstream_default_branch | TODO: e.g. master (older default) or main | Upstream's default branch — what <default-branch> resolves to. Distinct from tracker_default_branch (the security tracker repo's PR target) |
upstream_agents_md_url | TODO: https://github.com/<upstream>/blob/main/AGENTS.md | Conventions this repo mirrors |
upstream_contributing_docs_url | TODO | |
upstream_genai_disclosure_anchor | TODO: URL + anchor for the project's Gen-AI disclosure guideline | |
upstream_security_policy_url | TODO: https://github.com/<upstream>/security/policy |
Mailing lists
| Key | Value | Notes |
|---|---|---|
security_list | TODO: e.g. security@foo.apache.org | Inbound reports; not publicly archived |
private_list | TODO: e.g. private@foo.apache.org | PMC escalation; not publicly archived |
users_list | TODO: e.g. users@foo.apache.org | Public advisories end up here; publicly archived |
dev_list | TODO: e.g. dev@foo.apache.org | Release [RESULT][VOTE] threads; publicly archived |
announce_list | TODO: e.g. announce@apache.org | Cross-project announcement list; publicly archived |
commits_list | TODO: e.g. commits@foo.apache.org | Publicly archived |
Only URLs on publicly archived lists may appear in CVE references[] as
vendor-advisory; see ../../AGENTS.md and
security-model.md.
The foundation-wide security forwarding address (e.g. security@apache.org
for ASF projects) is org-level — inherited from your organization's
security_inbox.foundation_security_address. Do not declare it here.
Tools enabled
| Capability | Tool | Adapter directory | Config knobs declared here |
|---|---|---|---|
| Issue tracking + project board | github | ../../tools/github/ | tracker_repo, upstream_repo, github_project_board_*, issue_template_fields |
| Source control (VCS) | github (Git) — replaceable with a non-Git VCS | ../../tools/github/source-control.md | upstream_repo, default_branch; for a non-Git VCS declare the sibling tool + its working-copy URL |
| Inbound email / drafts | <one or more mail-source backends> | ../../tools/mail-source/contract.md (abstract) + per-backend adapter dirs (tools/gmail/, tools/ponymail/, tools/mail-source/imap/, tools/mail-source/mbox/, ...) | See Mail sources below — declare each backend's role (primary / preferred-for-<op> / fallback / optional) and mandatory flag |
| CVE allocation + record mgmt | org-level — inherited from organizations/<org>/organization.md → cve_authority.tool; for ASF: vulnogram (tools/cve-tool-vulnogram/), for independent: mitre-form | — | override in CVE authority only if this project differs from its org |
| Project metadata (rosters / people / releases) | org-level — inherited from organizations/<org>/organization.md → project_metadata.kind; for ASF: apache-projects (tools/apache-projects/), for independent: none | — | override in Project metadata only if this project differs from its org |
| Release comms | TODO: the backend that carries release announcements — for ASF: dev_list / announce_list / users_list; for GitHub Releases leave blank | — | whichever release-comms keys the org default or per-project override declares |
To replace a tool (e.g. swap GitHub issues for JIRA), declare an
alternate tool in the table above, add a tools/<name>/ adapter
directory, and make sure the values the generic skills need are still
reachable from this manifest.
CVE tooling
The CNA tool, allocation URL, record URL template, and allocation gate are
org-level — inherited from your organization's cve_authority and
governance blocks (see
organizations/ASF/organization.md
for ASF defaults,
organizations/independent/organization.md
for the GitHub-native baseline). Override a key in the
Security workflow configuration → CVE authority block only
if this project's CNA setup genuinely differs from its organization.
For ASF adopters, fill in the per-project CNA queue fields below — each ASF project has its own queue slug and org UUID, so these are not org-level:
| Key | Value |
|---|---|
asf_org_id | TODO: project's CNA org UUID — e.g. f0158376-9dc2-43b6-827c-5f631a4d8d09 |
cna_private_owner | TODO: e.g. foo (CNA_private.owner — the project slug inside the ASF CNA queue) |
cna_private_projecturl | TODO: e.g. https://foo.apache.org/ |
cna_private_userslist | TODO: e.g. users@foo.apache.org |
GitHub project board
If the project uses a Projects V2 board for its security-issue view,
declare the node IDs below. Fetch with the introspection query in
../../tools/github/project-board.md.
If the project does not run a board, leave the table blank — skills
treat missing board config as "no board reconciliation".
| Key | Value |
|---|---|
project_board_url | TODO |
project_board_number | TODO |
project_board_node_id | TODO |
status_field_node_id | TODO |
Status column → option-ID mapping (re-fetch if any write
returns not found):
| Column | Option ID |
|---|---|
Needs triage | TODO |
Assessed | TODO |
CVE allocated | TODO |
PR created | TODO |
PR merged | TODO |
Fix released | TODO |
Announced | TODO |
Mail sources
The skills treat every supported mail backend the same way —
through the abstract operations defined in
../../tools/mail-source/contract.md.
The adopter declares which backends are configured, what role
each plays, and whether any are mandatory. The skill's resolution
rule (see the contract) then picks the right backend per operation
at run time.
Backend declaration
One row per configured backend. Exactly one row carries
role: primary. Multiple rows may carry preferred for <op> to
override the primary for specific operations. fallback rows are
tried in order when no preferred / primary backend supports the op.
mandatory: yes means the skill refuses to run when that
backend is unavailable; no means the skill continues with the
remaining backends (and skips ops that no available backend supports).
| Backend | Role | Mandatory | Notes |
|---|---|---|---|
TODO: gmail | TODO: e.g. primary | TODO: yes / no | TODO: e.g. "Triager Gmail account subscribed to <security-list> and <private-list>" |
TODO: ponymail | TODO: e.g. fallback or preferred for thread_url | TODO: yes / no | TODO: e.g. "Read-only archive backstop; install per tools/ponymail/tool.md" |
TODO: (add more rows as needed — imap, mbox, project-specific adapter) |
Mail backend selection is org-level. The
mail_providerblock in your organization manifest sets the primary and fallback backends (for ASF:primary: gmail-mcp,fallback: ponymail; for independent:primary: none,fallback: none). Only declare backends here that override or extend what the organization manifest provides. For ASF projects where PonyMail is the inherited fallback, declare it here only to change itsmandatoryflag or role for this specific project; the backend itself is already wired by the organization. Install PonyMail per../../tools/ponymail/tool.md.
Reference adapter docs:
tools/gmail/tool.md (full read+write),
tools/ponymail/tool.md (read-only ASF archive),
tools/mail-source/imap/README.md (stub),
tools/mail-source/mbox/README.md (read-only offline archive — stub).
Per-backend config
Per-backend values the generic recipes substitute in. Only fill in the rows for backends declared above; leave the rest blank or remove the row.
| Key | Backend | Value |
|---|---|---|
security_list_domain | gmail | TODO: e.g. security.foo.apache.org — Gmail list: operator uses the domain form |
ponymail_private_search_url_template | ponymail | TODO |
ponymail_public_search_url_template | ponymail | TODO |
ponymail_api_url_template | ponymail | TODO |
ponymail_thread_url_template | ponymail | https://lists.apache.org/thread/<hash>?<list> |
imap_host | imap | TODO: e.g. imap.example.org |
imap_account | imap | TODO: e.g. security-triage@example.org |
imap_security_list_folder | imap | TODO: e.g. INBOX.security-list |
imap_drafts_folder | imap | TODO: e.g. Drafts (or leave blank to declare create_draft unsupported on this adapter) |
mbox_archive_path | mbox | TODO: e.g. /srv/audit/security-list-2024.mbox |
Issue-template fields
The skills' body-field roles map to the following concrete ###
headings in the project's issue template (the concrete YAML file lives in the
adopter's <upstream> repo; the generic role → field contract is in The generic role → GitHub-field
contract lives in
../../tools/github/issue-template.md;
the concrete names below are what skills read and write for this
project.
| Role (generic) | Field name | Template type | Required? |
|---|---|---|---|
issue-description | TODO | textarea | TODO |
public-summary | TODO | textarea | TODO |
affected-versions | TODO | input | TODO |
security-thread | TODO | input | TODO |
public-advisory-url | TODO | input | TODO |
reporter-credit | TODO | input | TODO |
pr-with-fix | TODO | input | TODO |
cwe | TODO | input | TODO |
severity | TODO | dropdown | TODO |
cve-tool-link | TODO | input | TODO |
Security workflow configuration
Skills resolve every workflow knob from the three-layer chain
project.md → organizations/<org>/organization.md → framework default
(see AGENTS.md § Configuration resolution order).
The organization you named under Identity supplies the org-wide
defaults — the CNA tool, the governance gate, the mail / forwarder /
archive backends, the project-metadata source, and the release-manager
lookup cascade. For an ASF project these resolve to the Vulnogram /
PonyMail / apache-projects-mcp / ASF-security values in
organizations/ASF/organization.md;
organization: independent inherits the GitHub-native baseline in
organizations/independent/organization.md.
Declare below only what is specific to this project. Each block that is purely org-level says so and shows nothing — copy the matching key from the organization manifest down into that block only to override it (the project value wins). The blocks that every adopter fills in keep their per-project keys.
CVE authority
Org-level — inherited from your organization's cve_authority block
(CNA tool, allocate / record / source-tab URLs, state mapping,
propagation, allocation-email flag, reviewer channel). Override a single
key here only if this project's CNA setup differs from its organization.
Governance
Org-level except the escalation contact: the allocation gate, gate label, release-vote gating, private governance list, and roster URL are inherited. Declare this project's escalation contact:
governance:
# GitHub handle (or external contact) the skills cc / @-mention when
# escalating beyond the security team.
# Consumed by: security-issue-sync, pr-management-triage.
escalation_contact: "@<escalation-contact>"
Security inbox
Org-level except the concrete address: the inbox kind, the foundation
security address, the has_forwarder_relay flag, and the list filter are
inherited. Declare this project's inbound address:
security_inbox:
# The concrete inbound address / channel ID / form URL for this project.
# Consumed by: security-issue-import, security-issue-sync, canned-responses.
address: <security-list>
Forwarders
Org-level — inherited from your organization's forwarders block (which
relay adapters are enabled and their per-adapter detect / credit rules).
Override here only to enable an extra relay this project uses.
Mail provider
Org-level — inherited from your organization's mail_provider block
(primary + fallback mail backends). Override here only if this project
reads mail from a different backend than its organization.
Archive system
Org-level — inherited from your organization's archive_system block
(public-archive backend + URL templates). Override here only if this
project's advisories surface on a different archive than its organization.
Project metadata
Org-level — inherited from your organization's project_metadata block
(roster / people / releases backend + whether it is mandatory). Override
here only if this project uses a different metadata source.
Tracker
The tracker platform, board, visibility, and skill_url_template
are org-level defaults — override them here only if this project differs
(e.g. a project that runs its security tracker publicly sets
visibility: public). Declare this project's per-tracker vocabulary:
tracker:
# Whether the reporter can see the tracker issue once opened.
reporter_has_access: false
# Whether the tracker drives a board / kanban view.
project_board_enabled: true
# Body-field heading names — role -> the concrete `###` heading in this
# project's issue template. Skills refer to these by role.
# Consumed by: every skill that reads/writes the issue body.
body_fields:
cve_link: "CVE tool link"
mailing_thread: "Mailing list thread URL"
affected_versions: "Affected versions"
# Tracker labels — role -> the concrete label name in this project.
# Consumed by: security-issue-triage, security-issue-sync, pr-management-triage.
labels:
security_marker: "security"
needs_triage: "needs triage"
pr_open: "pr created"
pr_merged: "pr merged"
cve_allocated: "cve allocated"
not_cve_worthy: "not cve worthy"
# Label on the single open "rejected without tracker" ledger issue
# (see below). NOT the security_marker label.
rejections_ledger: "rejections-ledger"
Rejected-without-tracker ledger
The security-issue-import skill sometimes rejects a report with a
canned reply without creating a tracker (the disposition lives only
on the mail thread). To keep those rejections countable, the team
records each one as a comment on a single dedicated ledger issue in
tracker_repo: one open issue, labelled with the
tracker.labels.rejections_ledger value (default rejections-ledger)
and not carrying the security-marker label.
Adopters who want the rejected without tracker dashboard stat must:
- Create the ledger issue once in
tracker_repoand label itrejections-ledger(keep it open; the skills resolve it viagh issue list --repo <tracker> --state open --label rejections-ledger). - Set the dashboard knob. Point
security-tracker-stats.md → rejections_ledger_label(or therejections_ledger_label:key in the renderer's YAML overlay) at the same label. Set it tonullto disable the stat — then no ledger issue is needed.
Each rejection comment carries a machine-parseable block
(<!-- rejection v1 --> with date: / reporter: / canned: /
thread: / summary: lines); a one-time historical backfill is a
single <!-- rejection-backfill v1 count: N --> comment. The
security-tracker-stats-dashboard renderer parses these and excludes the
ledger issue from all tracker classification. Closes handled by
security-issue-invalidate are not ledger entries.
Scope detection
Per-project — whether this project distinguishes scope sub-products, and the label → sub-product map:
scope_detection:
# When false, every issue maps to the single product in the `product` block.
# Consumed by: security-issue-triage, generate-cve-json, security-issue-sync.
enabled: true
# Scope label -> sub-product: tracker label -> CVE product / packageName
# / upstream path-prefix the skill uses to confirm a PR touches that scope.
labels:
<scope-label>:
product: "<Product Name>"
packageName: "<package-name>"
path_prefix: "<path-prefix-regex>"
<secondary-scope-label>:
product: "<Secondary Product Name>"
packageName: "<secondary-package-name>"
path_prefix: "<secondary-path-prefix-regex>"
Release process
The release-manager lookup cascade and artifact registries are org-level and inherited. Declare this project's stale milestones and changelog fragment tool:
release_process:
# Milestones the skills treat as "stale" (overdue for re-targeting) —
# exact milestone-name matches.
# Consumed by: security-issue-sync, pr-management-triage.
stale_milestones:
- "<stale-milestone-1>"
- "<stale-milestone-2>"
# Whether the upstream repo uses a changelog-fragment tool, and which one.
# Consumed by: security-issue-fix, issue-fix-workflow.
newsfragments:
enabled: true
tool: <fragment-tool>
Roster
The roster source is org-level and inherited. Declare this project's
bare-name → handle map and release managers:
roster:
# Mailing-list threads reference contributors by first name; this binds
# those to GitHub handles for @-mentions.
# Consumed by: security-issue-sync, pr-management-mentor.
bare_name_handles:
# Example (replace with your project's contributors):
"<FirstName>": "@<handle>"
# Release-manager handles, current first. Keep in sync with release-trains.md.
# Consumed by: security-issue-sync, security-issue-fix.
release_managers:
# Example (replace with your project's release managers):
- "@<handle>"
Product
Per-project — the product identity used in CVE records, advisories, and title normalization:
product:
# Human-readable product name — lands in the CVE record's `product` field.
# Consumed by: generate-cve-json, canned-responses templating.
name: <ProjectShortName>
# Package-name shape for the primary artifact (PyPI / npm / Maven).
# Consumed by: generate-cve-json, canned-responses templating.
package_name: <package-name>
# Regex matched against changed paths in an upstream PR to confirm
# "this PR really touches the product" — a backstop in the fix flow.
# Consumed by: security-issue-fix, pr-management-triage.
code_pointer_path_prefix: "<code-path-prefix-regex>"
# Prefixes the title-normalization skill strips from an inbound subject
# when building a CVE title (matched at the start, case-insensitively).
# Consumed by: title-normalization, generate-cve-json, canned-responses.
subject_prefix_strip:
- "[SECURITY]"
- "[Security Report]"
- "Re:"
- "Fwd:"
- "<vendor>:"
- "<vendor> <product>:"
# Prefix the affected-versions extractor strips to leave the bare version.
# Consumed by: security-issue-sync, generate-cve-json.
affected_version_extract_prefix: "<ProjectShortName>"
Pointers to sibling files
release-trains.md— fast-moving release state, release-manager attribution, security-team roster.milestones.md— milestone naming conventions.scope-labels.md— scope label → CVE product mapping.security-model.md— Security-Model URL + anchors.title-normalization.md— CVE title strip cascade.fix-workflow.md— fork / toolchain / commit-trailer specifics.naming-conventions.md— project-specific editorial rules.canned-responses.md— reporter-facing reply templates.skill-sources.md— trusted external skill sources this project pulls skills from (the install gate).README.md— project file index + onboarding checklist.