Skip to content

feat(approuter): serve .well-known/security.txt + automate upstream drift check - #1573

Merged
jung-thomas merged 1 commit into
mainfrom
worktree-security-txt-automation
Aug 10, 2026
Merged

feat(approuter): serve .well-known/security.txt + automate upstream drift check#1573
jung-thomas merged 1 commit into
mainfrom
worktree-security-txt-automation

Conversation

@jung-thomas

Copy link
Copy Markdown
Contributor

What

Serve SAP's canonical security.txt (RFC 9116) from our approuter, and automate keeping it in sync with SAP's upstream.

Why

  • https://developers.sap.com/.well-known/security.txt returns 200 today — but from the AEM/Akamai edge, which is being decommissioned. Our own approuter returns 404 for that path (the /.well-known/* route proxies to CAP srv-api, which serves only oauth-* + agent-card.json). Once the vanity host points fully at our origin, security.txt disappears unless we serve it.
  • github.tools.sap/sgsc-engineering-and-automation/securitytxt (SGSC PSRT) is the source of truth, not a push service — its README says business owners own deployment. So we serve the content and auto-detect upstream changes.

How

  • approuter/lib/security-txt.js(req,res,next) handler + exported canonical constant. Modeled exactly on approuter/lib/well-known-oauth.js. Served as insertMiddleware.first so it survives the content-rebuild tarball swap that wipes approuter/static/ (a Hugo static file would not).
  • approuter/server.js — wired right after wellKnownOAuthHandler.
  • .github/workflows/security-txt-drift.yml — weekly (Mon 05:19 UTC) + workflow_dispatch + PR-path trigger. Diffs our copy against https://www.sap.com/.well-known/security.txt (SAP's public mirror; the internal repo is unreachable from GitHub.com runners). On drift it opens/updates a PR (GitHub App token, USE_GITHUB_APP gated) — never auto-merges/deploys.
  • scripts/check-security-txt-drift.cjs — fetch + compare, exit 2 on drift; npm run check:security-txt-drift.
  • Tests: test/unit/security-txt.test.js (7 cases) + a live smoke assertion in test/smoke/seo-files.test.js.

Verification (all green locally)

  • vitest run test/unit/security-txt.test.js test/unit/well-known-oauth.test.js21 passed (oauth unaffected).
  • Handler-chain probe (real handlers, server.js order): /.well-known/security.txt → 200 text/plain; oauth-protected-resource / oauth-authorization-server → 200 JSON; HEAD → 200 no body.
  • node scripts/check-security-txt-drift.cjs → exit 0 (matches upstream); stale-constant probe → exit 2 with captured upstream.
  • Drift-PR content regeneration tested (multi-line incl. a new Encryption: field) → byte-identical to upstream.

Deploy note

Approuter-only change. Requires a full approuter deploy (npm run deploy -- --env <env>, no --skip-build) — the middleware ships with the approuter module. Roll DEV → verify → PROD.

…rift check

Serve SAP's canonical security.txt (RFC 9116) from the approuter as
insertMiddleware.first (mirrors well-known-oauth.js), so it survives the
content-rebuild tarball swap that wipes approuter/static/. The AEM/Akamai
edge that historically served developers.sap.com/.well-known/security.txt
is being decommissioned; our own approuter returned 404 for it.

Automate maintenance with a weekly workflow that diffs our served copy
against SAP's public mirror (www.sap.com/.well-known/security.txt) and
opens/updates a PR when SGSC changes the upstream (e.g. Expires bump).
Diffs www.sap.com, not the internal github.tools.sap source repo, which
is unreachable from GitHub.com hosted runners.

- approuter/lib/security-txt.js: handler + canonical constant (single source)
- approuter/server.js: wire handler after wellKnownOAuthHandler
- scripts/check-security-txt-drift.cjs: fetch+compare, exit 2 on drift
- .github/workflows/security-txt-drift.yml: schedule/dispatch/PR-path; PR-on-drift
- test/unit/security-txt.test.js: 7 cases (mirrors well-known-oauth.test.js)
- test/smoke/seo-files.test.js: live 200 + Contact/Expires assertion
- package.json: check:security-txt-drift script
@jung-thomas
jung-thomas merged commit f8ca6a8 into main Aug 10, 2026
6 checks passed
@jung-thomas
jung-thomas deleted the worktree-security-txt-automation branch August 10, 2026 10:56
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