Skip to content

feat(security): forwarder-relay + mail-archive sub-tools (PR3/5)#387

Merged
potiuk merged 1 commit into
apache:mainfrom
potiuk:feat-security-genericization-pr3-forwarder-archive
May 30, 2026
Merged

feat(security): forwarder-relay + mail-archive sub-tools (PR3/5)#387
potiuk merged 1 commit into
apache:mainfrom
potiuk:feat-security-genericization-pr3-forwarder-archive

Conversation

@potiuk

@potiuk potiuk commented May 30, 2026

Copy link
Copy Markdown
Member

Summary

Third of 5 PRs converting the security skill family from
Airflow/ASF-coupled to a generic framework with ASF as the
default-configured option.

PR1 (#381)
landed the adapter contracts. PR2
(#386)
lifted 6 config-driven skills. This PR extracts the
ASF-Security forwarder + PonyMail archive specifics out of the
generic skill bodies
into:

  • a new optional sub-skill that the generic intake / invalidate
    / sync skills invoke when forwarders.enabled is non-empty
  • explicit cross-references from the adapter-contract READMEs
    to their default-ASF implementations

Byte-equivalent for the airflow-s adopter. Every behaviour
the ASF-relay row + Step 5d + Step 2b previously produced is
now reachable via the sub-skill, which the airflow-s adopter
installs by default (forwarders.enabled: [asf-security]).

New optional sub-skill

.claude/skills/security-issue-import-via-forwarder/SKILL.md
(+620 lines). Adapter-agnostic body — no asf-security /
huntr-relay / hackerone-relay string in control flow.

The body reads enabled adapters from forwarders.enabled in
project.md and dispatches via detect() / extract_credit()
/ reporter_addressing_block() from
tools/forwarder-relay/README.md.

Step What it does
Step 0 — Pre-flight check forwarders.enabled non-empty?
Step 1 — Detect adapter match Run each registered forwarder's preamble_match regex
Step 2 — Extract reporter credit Per adapter's credit_extraction_rule (bot/AI policy applied to the extracted string)
Step 3 — Route reporter-facing drafts Use adapter's contact_handle + reporter_addressing_block
Step 4 — Hand back to parent skill With extracted credit + routing decision

Frontmatter: capability: capability:intake.

Skill lifts (existing bodies)

Skill Lines What was lifted
security-issue-import -60/+54 (net -6) Step 3 classification table: dropped the ASF-security relay row; added a pre-classification paragraph pointing at the sub-skill when forwarders.enabled is non-empty. Step 7 receipt-of-confirmation routing generalized. Golden-rule prose, Step 4 field-extraction header, Step 5 proposal grouping, Step 6 default-disposition, rollup provenance template, Hard Rules — all Report / ASF-security relay pairings collapsed to a single generalized treatment with the ASF case as a named example.
security-issue-invalidate -49/+93 (+44) Step 5d ASF-relay inline logic replaced with adapter-aware routing through the sub-skill. Four touch-points lifted: GHSA-relay-no-write-access bullet, Step 5d.1 via-forwarder recipients, Step 5d.2 reporter-addressing-block, the worked-example. ASF retained as a named example in the worked-example sections.
security-issue-sync -20/+20 (±0) Scoped Step 2b lift only. The big Vulnogram-state-machine rewrite at Steps 5b/5c (~600 lines) stays for PR4. Draft routing in Step 2b now reads adapter metadata from the sub-skill's hand-back; no inline Dear PMC preamble match.

Adapter-contract README cross-references

File Change
tools/forwarder-relay/README.md +24 — explicit "Implementation: tools/gmail/asf-relay.md" pointer for the asf-security adapter + sub-skill consumer link
tools/mail-archive/README.md +19 — explicit "Implementation: tools/ponymail/" pointer + the skills that consume PonyMail today (intake / sync / invalidate)

Doc table

docs/labels-and-capabilities.md gets a new row for
security-issue-import-via-forwardercapability:intake
(satisfies the capability-sync check landed in #340).

Aggregate

7 files changed, +795 / -116 lines.

What is not in this PR

  • tools/vulnogram/, tools/gmail/asf-relay.md bodies are
    not modified.
    Only cross-references TO them are updated.
    The CVE-authority sub-tool extract is PR4.
  • tools/ponymail/ body is not modified. Same reasoning.
  • security-issue-sync Steps 5b/5c — the ~600-line CVE-
    state-machine section — is PR4.
  • security-cve-allocate Vulnogram-specific body is PR4.
  • docs/security/process.md, forwarder-routing-policy.md,
    roles.md, threat-model.md
    are PR5.

Test plan

  • uv run --project tools/skill-and-tool-validator skill-and-tool-validate
    clean (5 soft advisory warnings, none hard).
  • pytest clean for the validator (218 tests).
  • All pre-commit hooks pass.
  • Spot-read the new sub-skill on GitHub to confirm the
    adapter-agnostic body reads correctly and the Step 1-4
    hand-back contract is unambiguous.
  • Confirm the airflow-s adopter, with
    forwarders.enabled: [asf-security], still gets the same
    behaviour as today (byte-equivalence invariant).

Third of 5 PRs converting the security skill family from
Airflow/ASF-coupled to a generic framework.

PR1 (apache#381) landed the adapter contracts. PR2 (apache#386) lifted the
config-driven skills. This PR extracts the ASF-Security
forwarder + PonyMail archive specifics into:

- a new optional sub-skill `security-issue-import-via-forwarder`
  that the generic intake/invalidate/sync skills invoke when
  `forwarders.enabled` is non-empty
- explicit cross-references from the adapter-contract READMEs
  to their default-ASF implementations (`tools/gmail/asf-relay.md`
  for the asf-security forwarder; `tools/ponymail/` for the
  ponymail mail-archive)

Byte-equivalent for the airflow-s adopter: every behaviour the
ASF-relay row + Step 5d + Step 2b previously produced is now
reachable via the sub-skill, which the airflow-s adopter
installs by default (`forwarders.enabled: [asf-security]`).

== New sub-skill ==

`.claude/skills/security-issue-import-via-forwarder/SKILL.md`
(+620 lines). Adapter-agnostic body — no `asf-security` /
`huntr-relay` / `hackerone-relay` string in control flow.
Reads enabled adapters from `forwarders.enabled` in
project.md, dispatches via `detect()` / `extract_credit()` /
`reporter_addressing_block()` from
`tools/forwarder-relay/README.md`. Four steps:

  Step 0 — Pre-flight check
  Step 1 — Detect adapter match
  Step 2 — Extract reporter credit
  Step 3 — Route reporter-facing drafts
  Step 4 — Hand back to parent skill

Frontmatter: `capability: capability:intake`. Validator clean.

== Skill lifts ==

- security-issue-import (-60/+54 net -6) — dropped the
  ASF-security-relay row from the Step 3 classification table;
  replaced with a pre-classification paragraph that points at
  the sub-skill when `forwarders.enabled` is non-empty.
  Generalized the Step 7 receipt-of-confirmation routing and
  every other inline `ASF-security relay` / `Report` pairing
  (golden-rule prose, Step 4 field-extraction header, Step 5
  proposal grouping, Step 6 default-disposition, rollup
  provenance template, Hard Rules).

- security-issue-invalidate (-49/+93 +44) — Step 5d ASF-relay
  inline logic replaced with adapter-aware routing through the
  sub-skill + `tools/forwarder-relay/README.md`. Four touch-
  points lifted; ASF retained as a named example in worked-
  example sections.

- security-issue-sync (-20/+20 ±0) — scoped Step 2b lift only
  (the big Vulnogram-state-machine rewrite at Steps 5b/5c is
  PR4). Draft routing now reads adapter metadata from the
  sub-skill's hand-back; no inline `Dear PMC` preamble match.

== Adapter-contract README cross-references ==

- tools/forwarder-relay/README.md (+24) — explicit
  "Implementation: tools/gmail/asf-relay.md" pointer for the
  asf-security adapter + sub-skill consumer link.

- tools/mail-archive/README.md (+19) — explicit
  "Implementation: tools/ponymail/" pointer + the skills
  that consume PonyMail today (intake / sync / invalidate).

== Doc table ==

docs/labels-and-capabilities.md gets a new row for
`security-issue-import-via-forwarder` → `capability:intake`
(satisfies the capability-sync check).

Aggregate: 7 files changed, +795/-116. Validator clean
(5 advisory soft warnings, none hard, none on PR1/PR2-touched
files). 218 tests green.

Out of scope (deferred to PR4/PR5):

- `tools/vulnogram/`, `tools/gmail/asf-relay.md` bodies (this
  PR only updates cross-references TO them, not their content)
- `tools/ponymail/` body (same)
- `security-issue-sync` Steps 5b/5c CVE-state-machine rewrite
  (PR4 — the ~600-line section)
- `security-cve-allocate` Vulnogram-specific body (PR4)
- `docs/security/process.md`, `forwarder-routing-policy.md`,
  `roles.md`, `threat-model.md` (PR5)

Generated-by: Claude Code (Opus 4.7)
@potiuk potiuk merged commit 284dd81 into apache:main May 30, 2026
16 checks passed
potiuk added a commit that referenced this pull request May 30, 2026
Fifth and final PR of the security genericization series.

Lifts the remaining 4 docs in docs/security/ to read config knobs
from projects/_template/project.md and the contract docs from
PR1-PR4 (cve_authority.*, governance.*, security_inbox.*,
forwarders.*, archive_system.*, scope_detection.*). Plus a final
scrub of 4 skills for leftover ASF/Vulnogram literals.

Byte-equivalent for the airflow-s adopter: every ASF/Airflow/
Vulnogram-specific value either resolves through a config knob
whose ASF default matches today's behaviour, OR stays as one
named-example aside in generic prose.

Per-target lifts:

- docs/security/threat-model.md (+107/-77) — Purpose/Scope/
  Assumptions reframed from "ASF"/"PMC" to governance-knob
  terms. STRIDE matrix rows A.6/A.7/C.1-C.4/E.1-E.2 lifted:
  Vulnogram -> <cve-tool>; security@apache.org -> <security-list>;
  DRAFT/REVIEW/READY/PUBLIC -> cve_authority.states sequence
  (allocated -> review-ready -> publish-ready -> public).
  Mitigations M.10/M.16/M.18/M.19/M.27 + residual risks
  #3/#8/#10/#11 + re-audit cadence ownership generalised.

- docs/security/forwarder-routing-policy.md (+42/-27) — references
  the optional security-issue-import-via-forwarder sub-skill from
  PR3 (#387) and the tools/forwarder-relay/README.md contract.
  Replaces "ASF-security relay" / "security@apache.org" with
  forwarders.enabled / <security-list> / foundation_security_address.
  ASF-Airflow shown as a named-example aside per concept.

- docs/security/how-to-fix-a-security-issue.md (+20/-8) —
  "governance-authorised member of the adopting project (per
  governance.cve_allocation_gate)" replaces "PMC member of
  apache/airflow"; <cve-tool> + cve_authority.* replaces Vulnogram-
  specific URLs and state names; archive_system.advisory_publication_signal_url
  replaces the lists.apache.org users-list URL.

- docs/security/new-members-onboarding.md (+26/-13) — onboarding-
  style register preserved. "PMC members and committers" reframed
  as "governance body that satisfies governance.cve_allocation_gate";
  per-user-config "PMC status" steps reference the governance knob;
  Vulnogram steps reference <cve-tool> via cve_authority.record_url_template.

- Final scrub of 4 skills (+17/-15 net): security-issue-import,
  security-issue-import-via-forwarder, security-issue-invalidate,
  security-issue-fix — leftover literal references caught and
  lifted to roster.bare_name_handles / governance.escalation_contact /
  forwarders.<adapter>.contact_handle.

Aggregate: 8 files, +240/-156 lines.

That closes the series. Five PRs (#381, #386, #387, #388, this)
transitioned the security skill family from Airflow/ASF-coupled to a
generic framework with ASF as the default-configured option. The
airflow-s adopter, with the ASF defaults baked into project.md, sees
byte-equivalent behaviour throughout. Non-ASF adopters override
specific dimensions (CVE authority, mail provider, archive system,
governance gate, scope axis) by changing only their <project-config>/
files.

Generated-by: Claude Code (Opus 4.7)
potiuk added a commit to potiuk/magpie that referenced this pull request Jun 1, 2026
…ity-suite refactor patterns

Adds `optimize-skill` (capability:setup) — the refactoring sibling of
`write-skill`. It takes an existing framework skill (or sweeps a set)
and applies the five restructuring patterns proven on the security
suite, as behavior-preserving proposals gated by the validator
(green-before / green-after):

- split — slim an oversized SKILL.md into linked siblings (the apache#410
  pattern; addresses the PRINCIPLES.md P14 cap)
- config-lift — move concrete values into <project-config> (apache#386/apache#387/apache#388)
- out-of-context — read/PATCH one field without loading the body
  (apache#412 github-body-field, apache#424 github-rollup)
- fetch-upfront — batch per-item round-trips (apache#347)
- preflight-classifier — skip obvious no-ops before LLM passes (apache#414/apache#416)

SKILL.md is 297 lines; the pass catalogue (smell / exemplar PR /
mechanics / behavior-preservation guarantee / validation) lives in
the patterns.md sibling. Reads only framework-internal files, so no
injection-guard / Privacy-LLM callouts.

Ships a step-diagnose eval (5 auto-comparable cases incl. an
injection-resistance case) so the skill is not released without an
eval (P8). Wires the skill into the capability->skill map and the
eval index.

Generated-by: Claude Code (Opus 4.8)
potiuk added a commit to potiuk/magpie that referenced this pull request Jun 1, 2026
…ity-suite refactor patterns

Adds `optimize-skill` (capability:setup) — the refactoring sibling of
`write-skill`. It takes an existing framework skill (or sweeps a set)
and applies the five restructuring patterns proven on the security
suite, as behavior-preserving proposals gated by the validator
(green-before / green-after):

- split — slim an oversized SKILL.md into linked siblings (the apache#410
  pattern; addresses the PRINCIPLES.md P14 cap)
- config-lift — move concrete values into <project-config> (apache#386/apache#387/apache#388)
- out-of-context — read/PATCH one field without loading the body
  (apache#412 github-body-field, apache#424 github-rollup)
- fetch-upfront — batch per-item round-trips (apache#347)
- preflight-classifier — skip obvious no-ops before LLM passes (apache#414/apache#416)

SKILL.md is 297 lines; the pass catalogue (smell / exemplar PR /
mechanics / behavior-preservation guarantee / validation) lives in
the patterns.md sibling. Reads only framework-internal files, so no
injection-guard / Privacy-LLM callouts.

Ships a step-diagnose eval (5 auto-comparable cases incl. an
injection-resistance case) so the skill is not released without an
eval (P8). Wires the skill into the capability->skill map and the
eval index.

Generated-by: Claude Code (Opus 4.8)
potiuk added a commit that referenced this pull request Jun 1, 2026
…ity-suite refactor patterns (#427)

Adds `optimize-skill` (capability:setup) — the refactoring sibling of
`write-skill`. It takes an existing framework skill (or sweeps a set)
and applies the five restructuring patterns proven on the security
suite, as behavior-preserving proposals gated by the validator
(green-before / green-after):

- split — slim an oversized SKILL.md into linked siblings (the #410
  pattern; addresses the PRINCIPLES.md P14 cap)
- config-lift — move concrete values into <project-config> (#386/#387/#388)
- out-of-context — read/PATCH one field without loading the body
  (#412 github-body-field, #424 github-rollup)
- fetch-upfront — batch per-item round-trips (#347)
- preflight-classifier — skip obvious no-ops before LLM passes (#414/#416)

SKILL.md is 297 lines; the pass catalogue (smell / exemplar PR /
mechanics / behavior-preservation guarantee / validation) lives in
the patterns.md sibling. Reads only framework-internal files, so no
injection-guard / Privacy-LLM callouts.

Ships a step-diagnose eval (5 auto-comparable cases incl. an
injection-resistance case) so the skill is not released without an
eval (P8). Wires the skill into the capability->skill map and the
eval index.

Generated-by: Claude Code (Opus 4.8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant