redlinegate 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +188 -0
- package/commands/redline-init.md +54 -0
- package/commands/redline-verify.md +69 -0
- package/dist/bin/redline.js +605 -0
- package/dist/bin/redline.js.map +1 -0
- package/dist/commands/exempt.js +45 -0
- package/dist/commands/exempt.js.map +1 -0
- package/dist/commands/init.js +615 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/policy.js +25 -0
- package/dist/commands/policy.js.map +1 -0
- package/dist/commands/remove.js +427 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/review.js +72 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/sync.js +42 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/verify.js +478 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/config/redline-json.js +187 -0
- package/dist/config/redline-json.js.map +1 -0
- package/dist/core/errors.js +25 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/git.js +152 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/log.js +22 -0
- package/dist/core/log.js.map +1 -0
- package/dist/core/severity.js +16 -0
- package/dist/core/severity.js.map +1 -0
- package/dist/core/version.js +15 -0
- package/dist/core/version.js.map +1 -0
- package/dist/detect/scan.js +79 -0
- package/dist/detect/scan.js.map +1 -0
- package/dist/detect/stack.js +71 -0
- package/dist/detect/stack.js.map +1 -0
- package/dist/enforce/ladder.js +148 -0
- package/dist/enforce/ladder.js.map +1 -0
- package/dist/exempt/parse.js +86 -0
- package/dist/exempt/parse.js.map +1 -0
- package/dist/metrics/options.js +257 -0
- package/dist/metrics/options.js.map +1 -0
- package/dist/metrics/run.js +72 -0
- package/dist/metrics/run.js.map +1 -0
- package/dist/platforms/azure/client.js +53 -0
- package/dist/platforms/azure/client.js.map +1 -0
- package/dist/platforms/azure/index.js +69 -0
- package/dist/platforms/azure/index.js.map +1 -0
- package/dist/platforms/azure/install.js +917 -0
- package/dist/platforms/azure/install.js.map +1 -0
- package/dist/platforms/azure/policy-types.js +70 -0
- package/dist/platforms/azure/policy-types.js.map +1 -0
- package/dist/platforms/azure/verify.js +309 -0
- package/dist/platforms/azure/verify.js.map +1 -0
- package/dist/platforms/detect.js +40 -0
- package/dist/platforms/detect.js.map +1 -0
- package/dist/platforms/github/client.js +49 -0
- package/dist/platforms/github/client.js.map +1 -0
- package/dist/platforms/github/index.js +54 -0
- package/dist/platforms/github/index.js.map +1 -0
- package/dist/platforms/github/install.js +558 -0
- package/dist/platforms/github/install.js.map +1 -0
- package/dist/platforms/github/push.js +102 -0
- package/dist/platforms/github/push.js.map +1 -0
- package/dist/platforms/github/remote.js +36 -0
- package/dist/platforms/github/remote.js.map +1 -0
- package/dist/platforms/github/verify.js +366 -0
- package/dist/platforms/github/verify.js.map +1 -0
- package/dist/platforms/http.js +58 -0
- package/dist/platforms/http.js.map +1 -0
- package/dist/platforms/pull-request-templates.js +157 -0
- package/dist/platforms/pull-request-templates.js.map +1 -0
- package/dist/platforms/remote.js +21 -0
- package/dist/platforms/remote.js.map +1 -0
- package/dist/platforms/resolve.js +69 -0
- package/dist/platforms/resolve.js.map +1 -0
- package/dist/platforms/shape.js +19 -0
- package/dist/platforms/shape.js.map +1 -0
- package/dist/platforms/types.js +24 -0
- package/dist/platforms/types.js.map +1 -0
- package/dist/policy/checks.js +91 -0
- package/dist/policy/checks.js.map +1 -0
- package/dist/policy/diff.js +50 -0
- package/dist/policy/diff.js.map +1 -0
- package/dist/registry/discover.js +74 -0
- package/dist/registry/discover.js.map +1 -0
- package/dist/registry/serialize.js +41 -0
- package/dist/registry/serialize.js.map +1 -0
- package/dist/registry/types.js +2 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/remove/host.js +294 -0
- package/dist/remove/host.js.map +1 -0
- package/dist/render/commands.js +139 -0
- package/dist/render/commands.js.map +1 -0
- package/dist/render/manifest.js +82 -0
- package/dist/render/manifest.js.map +1 -0
- package/dist/render/markers.js +166 -0
- package/dist/render/markers.js.map +1 -0
- package/dist/render/profile.js +23 -0
- package/dist/render/profile.js.map +1 -0
- package/dist/render/standards.js +169 -0
- package/dist/render/standards.js.map +1 -0
- package/dist/render/vendors.js +199 -0
- package/dist/render/vendors.js.map +1 -0
- package/dist/review/engines/api.js +95 -0
- package/dist/review/engines/api.js.map +1 -0
- package/dist/review/engines/embedded.js +20 -0
- package/dist/review/engines/embedded.js.map +1 -0
- package/dist/review/engines/types.js +2 -0
- package/dist/review/engines/types.js.map +1 -0
- package/dist/review/glob.js +29 -0
- package/dist/review/glob.js.map +1 -0
- package/dist/review/prompt.js +45 -0
- package/dist/review/prompt.js.map +1 -0
- package/dist/review/rules.js +25 -0
- package/dist/review/rules.js.map +1 -0
- package/dist/review/schema.js +84 -0
- package/dist/review/schema.js.map +1 -0
- package/dist/review/scope.js +27 -0
- package/dist/review/scope.js.map +1 -0
- package/dist/sarif/map.js +58 -0
- package/dist/sarif/map.js.map +1 -0
- package/dist/sarif/parse.js +88 -0
- package/dist/sarif/parse.js.map +1 -0
- package/dist/sarif/types.js +2 -0
- package/dist/sarif/types.js.map +1 -0
- package/dist/sync/host.js +21 -0
- package/dist/sync/host.js.map +1 -0
- package/dist/sync/plan.js +47 -0
- package/dist/sync/plan.js.map +1 -0
- package/dist/sync/render.js +57 -0
- package/dist/sync/render.js.map +1 -0
- package/dist/sync/run.js +118 -0
- package/dist/sync/run.js.map +1 -0
- package/dist/verify/host.js +52 -0
- package/dist/verify/host.js.map +1 -0
- package/dist/verify/remote.js +146 -0
- package/dist/verify/remote.js.map +1 -0
- package/package.json +52 -0
- package/platforms/azure/gate-template.yml +105 -0
- package/rulesets/redline-org-ruleset.json +46 -0
- package/rulesets/redline-ruleset.json +49 -0
- package/scripts/assign-rule-ids.mjs +129 -0
- package/scripts/build-baseline.mjs +124 -0
- package/scripts/build-correlation.mjs +74 -0
- package/scripts/build-dashboard.mjs +584 -0
- package/scripts/build-digest.mjs +164 -0
- package/scripts/build-inbox.mjs +133 -0
- package/scripts/build-registry.mjs +42 -0
- package/scripts/build-roi.mjs +181 -0
- package/scripts/check-pins.mjs +88 -0
- package/scripts/collect-telemetry.mjs +300 -0
- package/scripts/lib/__tests__/baseline.test.mjs +132 -0
- package/scripts/lib/__tests__/correlate.test.mjs +131 -0
- package/scripts/lib/__tests__/dora.test.mjs +110 -0
- package/scripts/lib/__tests__/exemptions.test.mjs +85 -0
- package/scripts/lib/__tests__/metrics-scanner.test.mjs +65 -0
- package/scripts/lib/__tests__/sarif.test.mjs +125 -0
- package/scripts/lib/__tests__/spend.test.mjs +64 -0
- package/scripts/lib/baseline.mjs +156 -0
- package/scripts/lib/correlate.mjs +125 -0
- package/scripts/lib/dora.mjs +133 -0
- package/scripts/lib/exemptions.mjs +79 -0
- package/scripts/lib/metrics.mjs +172 -0
- package/scripts/lib/rules.mjs +107 -0
- package/scripts/lib/sarif.mjs +108 -0
- package/scripts/lib/spend.mjs +69 -0
- package/scripts/measure-context.mjs +101 -0
- package/scripts/render-self.mjs +18 -0
- package/scripts/score-seeds.mjs +294 -0
- package/scripts/validate.mjs +394 -0
- package/standards/core.md +124 -0
- package/standards/manifest.json +214 -0
- package/standards/stacks/csharp.md +29 -0
- package/standards/stacks/go.md +30 -0
- package/standards/stacks/java.md +30 -0
- package/standards/stacks/javascript.md +42 -0
- package/standards/stacks/kotlin.md +27 -0
- package/standards/stacks/microservices.md +37 -0
- package/standards/stacks/nodejs.md +34 -0
- package/standards/stacks/python.md +29 -0
- package/standards/stacks/react-native.md +29 -0
- package/standards/stacks/react.md +46 -0
- package/standards/stacks/swift.md +26 -0
- package/standards/stacks/terraform.md +27 -0
- package/templates/CODEOWNERS +29 -0
- package/templates/azure/pull_request_template.md +72 -0
- package/templates/github/pull_request_template.md +72 -0
- package/templates/redline.yml +35 -0
- package/templates/repo-context.md +64 -0
- package/workflows/dashboard.yml +119 -0
- package/workflows/inbox.yml +97 -0
- package/workflows/redline-collect.yml +61 -0
- package/workflows/redline-gate.yml +301 -0
- package/workflows/redline-sync.yml +79 -0
- package/workflows/seed-canary.yml +231 -0
- package/workflows/verify-onboarding.yml +115 -0
- package/workflows/weekly-digest.yml +78 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Reference shape only. `redline init` builds equivalent content in code and never reads
|
|
2
|
+
# this file — it writes .github/CODEOWNERS only on a repository that has none yet, and
|
|
3
|
+
# leaves an existing one untouched.
|
|
4
|
+
#
|
|
5
|
+
# The branch ruleset sets require_code_owner_review: true. Without a CODEOWNERS file that
|
|
6
|
+
# rule is a silent no-op, so the platform team must own at minimum the enforcement surface
|
|
7
|
+
# below — otherwise any contributor can weaken their own gate in a self-approved PR.
|
|
8
|
+
#
|
|
9
|
+
# Replace <org>/<team> placeholders before installing by hand.
|
|
10
|
+
|
|
11
|
+
# Default owner for everything not matched below.
|
|
12
|
+
* @<org>/<owning-team>
|
|
13
|
+
|
|
14
|
+
# --- Enforcement surface: platform team must approve any change here -------------------
|
|
15
|
+
# Editing the caller workflow, the ruleset, or the review standards changes what this
|
|
16
|
+
# repo is allowed to merge. These are the paths an attacker or a rushed engineer would
|
|
17
|
+
# touch to make the gate stop failing.
|
|
18
|
+
/.github/workflows/ @<org>/platform-engineering
|
|
19
|
+
/.github/CODEOWNERS @<org>/platform-engineering
|
|
20
|
+
/.github/copilot-instructions.md @<org>/platform-engineering
|
|
21
|
+
/.github/instructions/ @<org>/platform-engineering
|
|
22
|
+
/AGENTS.md @<org>/platform-engineering
|
|
23
|
+
/CLAUDE.md @<org>/platform-engineering
|
|
24
|
+
|
|
25
|
+
# --- Security-sensitive paths ---------------------------------------------------------
|
|
26
|
+
/infra/ @<org>/platform-engineering
|
|
27
|
+
/terraform/ @<org>/platform-engineering
|
|
28
|
+
Dockerfile @<org>/platform-engineering
|
|
29
|
+
/.github/dependabot.yml @<org>/platform-engineering
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Summary
|
|
2
|
+
|
|
3
|
+
<!-- What and why, 2-3 sentences. Link the ticket. -->
|
|
4
|
+
|
|
5
|
+
Ticket:
|
|
6
|
+
|
|
7
|
+
## Change type
|
|
8
|
+
|
|
9
|
+
<!-- Tick the one that applies. This section is NOT gated — pick one and move on. -->
|
|
10
|
+
|
|
11
|
+
- [ ] Feature
|
|
12
|
+
- [ ] Bugfix
|
|
13
|
+
- [ ] Refactor (approved beforehand)
|
|
14
|
+
- [ ] Chore/config
|
|
15
|
+
|
|
16
|
+
<!-- REDLINE:BEGIN — generated by Redline. Do not edit inside this block. -->
|
|
17
|
+
|
|
18
|
+
## Launch readiness
|
|
19
|
+
|
|
20
|
+
<!--
|
|
21
|
+
GATED SECTION. `redline-gate` fails while any box here is unticked.
|
|
22
|
+
If an item genuinely does not apply, delete the line and say why in the Summary.
|
|
23
|
+
Do not delete the heading — the gate fails if the section is missing.
|
|
24
|
+
-->
|
|
25
|
+
|
|
26
|
+
- [ ] No secrets, keys, or customer data in code, logs, or fixtures
|
|
27
|
+
- [ ] Input validated at boundaries touched by this change
|
|
28
|
+
- [ ] Typecheck and lint pass with no new errors
|
|
29
|
+
- [ ] Tested on: <!-- iOS / Android / web / staging -->
|
|
30
|
+
- [ ] Error states handled (network failure, empty, loading)
|
|
31
|
+
- [ ] Rollback is safe (no destructive migration, no breaking contract change)
|
|
32
|
+
- [ ] No unrelated changes in the diff
|
|
33
|
+
|
|
34
|
+
## Architecture decision
|
|
35
|
+
|
|
36
|
+
<!-- If this PR makes a non-obvious technical choice, add an ADR and link it. Otherwise delete this section. -->
|
|
37
|
+
|
|
38
|
+
ADR: `docs/adr/NNNN-*.md`
|
|
39
|
+
|
|
40
|
+
## Redline exemption
|
|
41
|
+
|
|
42
|
+
<!--
|
|
43
|
+
Only fill this in if a process check above is failing and you are asking to merge anyway.
|
|
44
|
+
Delete the whole section otherwise. A label alone no longer exempts anything: the gate
|
|
45
|
+
reads THIS block, and an exemption with no reason and no end date is an opt-out, not an
|
|
46
|
+
exemption.
|
|
47
|
+
|
|
48
|
+
- reason: what is being accepted and why, in a sentence a reader in three months
|
|
49
|
+
can act on. "Needed for release" is not one.
|
|
50
|
+
- until: YYYY-MM-DD, at most 90 days out. Longer than that is a standards change,
|
|
51
|
+
not an exemption — raise it in the Redline source repo.
|
|
52
|
+
- scope: which checks it covers (checklist, adr). Omit to cover both.
|
|
53
|
+
|
|
54
|
+
This can never exempt dependency review or the secret scan. Those do not soft-fail.
|
|
55
|
+
-->
|
|
56
|
+
|
|
57
|
+
- reason:
|
|
58
|
+
- until:
|
|
59
|
+
- scope:
|
|
60
|
+
|
|
61
|
+
<!-- REDLINE:END -->
|
|
62
|
+
|
|
63
|
+
## Automated review
|
|
64
|
+
|
|
65
|
+
- [ ] Review comments addressed, or dismissed in-thread with a reason
|
|
66
|
+
|
|
67
|
+
<!--
|
|
68
|
+
Gate stuck on a process check you cannot satisfy? Add the `redline-exempt` label to
|
|
69
|
+
this pull request and leave a comment explaining why. That downgrades the checklist
|
|
70
|
+
and ADR checks to warnings. It does NOT bypass dependency review or the secret scan —
|
|
71
|
+
those never soft-fail.
|
|
72
|
+
-->
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Summary
|
|
2
|
+
|
|
3
|
+
<!-- What and why, 2-3 sentences. Link the ticket. -->
|
|
4
|
+
|
|
5
|
+
Ticket:
|
|
6
|
+
|
|
7
|
+
## Change type
|
|
8
|
+
|
|
9
|
+
<!-- Tick the one that applies. This section is NOT gated — pick one and move on. -->
|
|
10
|
+
|
|
11
|
+
- [ ] Feature
|
|
12
|
+
- [ ] Bugfix
|
|
13
|
+
- [ ] Refactor (approved beforehand)
|
|
14
|
+
- [ ] Chore/config
|
|
15
|
+
|
|
16
|
+
<!-- REDLINE:BEGIN — generated by Redline. Do not edit inside this block. -->
|
|
17
|
+
|
|
18
|
+
## Launch readiness
|
|
19
|
+
|
|
20
|
+
<!--
|
|
21
|
+
GATED SECTION. `redline-gate` fails while any box here is unticked.
|
|
22
|
+
If an item genuinely does not apply, delete the line and say why in the Summary.
|
|
23
|
+
Do not delete the heading — the gate fails if the section is missing.
|
|
24
|
+
-->
|
|
25
|
+
|
|
26
|
+
- [ ] No secrets, keys, or customer data in code, logs, or fixtures
|
|
27
|
+
- [ ] Input validated at boundaries touched by this change
|
|
28
|
+
- [ ] Typecheck and lint pass with no new errors
|
|
29
|
+
- [ ] Tested on: <!-- iOS / Android / web / staging -->
|
|
30
|
+
- [ ] Error states handled (network failure, empty, loading)
|
|
31
|
+
- [ ] Rollback is safe (no destructive migration, no breaking contract change)
|
|
32
|
+
- [ ] No unrelated changes in the diff
|
|
33
|
+
|
|
34
|
+
## Architecture decision
|
|
35
|
+
|
|
36
|
+
<!-- If this PR makes a non-obvious technical choice, add an ADR and link it. Otherwise delete this section. -->
|
|
37
|
+
|
|
38
|
+
ADR: `docs/adr/NNNN-*.md`
|
|
39
|
+
|
|
40
|
+
## Redline exemption
|
|
41
|
+
|
|
42
|
+
<!--
|
|
43
|
+
Only fill this in if a process check above is failing and you are asking to merge anyway.
|
|
44
|
+
Delete the whole section otherwise. A label alone no longer exempts anything: the gate
|
|
45
|
+
reads THIS block, and an exemption with no reason and no end date is an opt-out, not an
|
|
46
|
+
exemption.
|
|
47
|
+
|
|
48
|
+
- reason: what is being accepted and why, in a sentence a reader in three months
|
|
49
|
+
can act on. "Needed for release" is not one.
|
|
50
|
+
- until: YYYY-MM-DD, at most 90 days out. Longer than that is a standards change,
|
|
51
|
+
not an exemption — raise it in the Redline source repo.
|
|
52
|
+
- scope: which checks it covers (checklist, adr). Omit to cover both.
|
|
53
|
+
|
|
54
|
+
This can never exempt dependency review or the secret scan. Those do not soft-fail.
|
|
55
|
+
-->
|
|
56
|
+
|
|
57
|
+
- reason:
|
|
58
|
+
- until:
|
|
59
|
+
- scope:
|
|
60
|
+
|
|
61
|
+
<!-- REDLINE:END -->
|
|
62
|
+
|
|
63
|
+
## Automated review
|
|
64
|
+
|
|
65
|
+
- [ ] Review comments addressed, or dismissed in-thread with a reason
|
|
66
|
+
|
|
67
|
+
<!--
|
|
68
|
+
Gate stuck on a process check you cannot satisfy? Apply the `redline-exempt` label AND
|
|
69
|
+
fill in the `## Redline exemption` section above. The label says a check was waived; the
|
|
70
|
+
block says who accepted what, why, and until when — and the gate reads the block.
|
|
71
|
+
It does NOT bypass dependency review or the secret scan — those never soft-fail.
|
|
72
|
+
-->
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Managed by Redline; regenerate with `redline init` rather than editing here.
|
|
2
|
+
# Redline caller. Installed into every onboarded repo as .github/workflows/redline.yml
|
|
3
|
+
# by `redline init`. Kept in sync by workflows/redline-sync.yml once `redline sync`
|
|
4
|
+
# ships in Phase 3 — see CHANGELOG.md.
|
|
5
|
+
#
|
|
6
|
+
# DO NOT RENAME THE JOB. The branch ruleset requires the check "redline-gate / gate",
|
|
7
|
+
# which is derived from this job id plus the aggregate job id in the reusable workflow.
|
|
8
|
+
# Renaming it makes the required check unreportable and blocks every PR in this repo.
|
|
9
|
+
#
|
|
10
|
+
# Replace <org> with the organisation that hosts the `.github` repo.
|
|
11
|
+
name: Redline
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
pull_request:
|
|
15
|
+
types: [opened, synchronize, reopened, edited, labeled, unlabeled, ready_for_review]
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
pull-requests: write
|
|
20
|
+
|
|
21
|
+
concurrency:
|
|
22
|
+
group: redline-${{ github.event.pull_request.number }}
|
|
23
|
+
cancel-in-progress: true
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
redline-gate:
|
|
27
|
+
uses: <org>/.github/.github/workflows/redline-gate.yml@main
|
|
28
|
+
with:
|
|
29
|
+
adr-diff-threshold: 300
|
|
30
|
+
fail-on-dependency-severity: high
|
|
31
|
+
soft-fail-labels: redline-exempt,redline-sync
|
|
32
|
+
# Written by `redline init --rung`. observe and warn report without blocking;
|
|
33
|
+
# block-blocker and block-high stop a merge. The security floor — dependency
|
|
34
|
+
# review and the secret scan — is not on this ladder and blocks at every rung.
|
|
35
|
+
rung: observe
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Project context
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
TEMPLATE. Copy the content of this file to the TOP of the target repo's AGENTS.md,
|
|
5
|
+
above the `<!-- REDLINE:BEGIN -->` marker, and fill the bracketed sections.
|
|
6
|
+
|
|
7
|
+
Everything above the marker is owned by your team and is never overwritten by
|
|
8
|
+
Redline sync. Everything inside the marker block is generated — do not edit it.
|
|
9
|
+
|
|
10
|
+
Why this file matters: review quality is bounded by context. A reviewer that does
|
|
11
|
+
not know FlashList is the standard cannot flag FlatList.
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
## What this repo is
|
|
15
|
+
|
|
16
|
+
[One paragraph: product name, what it does, who uses it, which market. e.g. "Customer
|
|
17
|
+
self-care app for <market>, React Native (Expo) plus shared web components."]
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
- **App shell:** [Expo SDK NN / Next.js NN / Spring Boot N.N / NestJS NN]
|
|
22
|
+
- **State:** server state via [TanStack Query]; client UI state via [Zustand]. No Redux.
|
|
23
|
+
- **Navigation:** [expo-router / react-navigation native-stack]
|
|
24
|
+
- **Styling:** [StyleSheet.create / Nativewind / styled-components]
|
|
25
|
+
- **API layer:** [BFF at `src/api/`; types generated from OpenAPI into `src/api/types/`]
|
|
26
|
+
- **Persistence:** [Postgres via Prisma / JPA + Flyway]
|
|
27
|
+
- **Messaging:** [Kafka topics owned: ...]
|
|
28
|
+
- **Lists:** [FlashList is the standard; FlatList only for legacy screens.]
|
|
29
|
+
- **Images:** [expo-image everywhere.]
|
|
30
|
+
|
|
31
|
+
## Directory map
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
src/
|
|
35
|
+
api/ # BFF client + generated types — do not hand-edit generated files
|
|
36
|
+
components/ # shared UI, design-system components
|
|
37
|
+
screens/ # one folder per screen
|
|
38
|
+
hooks/ # shared hooks
|
|
39
|
+
utils/ # pure functions only, no framework imports
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Team conventions
|
|
43
|
+
|
|
44
|
+
- [TypeScript strict mode; `noUncheckedIndexedAccess` on.]
|
|
45
|
+
- Error handling only at boundaries (API calls, storage, native modules, user input).
|
|
46
|
+
- Comments only for non-obvious WHY, never WHAT.
|
|
47
|
+
- Minimal diffs; no drive-by refactors in feature PRs.
|
|
48
|
+
- Architecture decisions recorded as ADRs in `docs/adr/NNNN-title.md`.
|
|
49
|
+
|
|
50
|
+
## Deliberate deviations from Redline
|
|
51
|
+
|
|
52
|
+
<!--
|
|
53
|
+
List rules this repo knowingly does not follow, with the reason. Reviewers should not
|
|
54
|
+
re-raise these. If the list grows past a few entries, the standard is wrong — raise it
|
|
55
|
+
in the Redline source repo instead of accumulating exceptions here.
|
|
56
|
+
-->
|
|
57
|
+
|
|
58
|
+
- [e.g. "`any` permitted in `src/legacy/**` until MIG-4412 completes."]
|
|
59
|
+
|
|
60
|
+
## Review context
|
|
61
|
+
|
|
62
|
+
- PRs may be authored by AI coding agents or contractors — review with the same rigour.
|
|
63
|
+
- Merge requires one human approval plus green required checks. Automated review is
|
|
64
|
+
advisory input to the human reviewer; it never approves.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Lives in the redline-metrics repo. Rebuilds the Redline dashboard from collected
|
|
2
|
+
# telemetry and publishes it to GitHub Pages.
|
|
3
|
+
#
|
|
4
|
+
# SECURITY: the page lists repo names, rule ids and finding counts. Set the Pages site to
|
|
5
|
+
# private or internal visibility BEFORE enabling this. The build refuses to run until
|
|
6
|
+
# PAGES_VISIBILITY_ACKNOWLEDGED is set as a repository variable.
|
|
7
|
+
name: Redline Dashboard
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: '30 5 * * *'
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
workflow_run:
|
|
14
|
+
# Rebuild as soon as new telemetry lands, so the page is never a day behind the data.
|
|
15
|
+
workflows: [Redline Collect, Redline Seed Canary]
|
|
16
|
+
types: [completed]
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
pages: write
|
|
21
|
+
id-token: write
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: dashboard
|
|
25
|
+
cancel-in-progress: true
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
build:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
timeout-minutes: 15
|
|
31
|
+
steps:
|
|
32
|
+
- name: Confirm Pages visibility was reviewed
|
|
33
|
+
env:
|
|
34
|
+
ACK: ${{ vars.PAGES_VISIBILITY_ACKNOWLEDGED }}
|
|
35
|
+
run: |
|
|
36
|
+
if [[ "${ACK:-}" != "private" && "${ACK:-}" != "internal" ]]; then
|
|
37
|
+
echo "::error::Set the repository variable PAGES_VISIBILITY_ACKNOWLEDGED to 'private' or 'internal' after confirming the Pages site is not public. This page exposes org-wide delivery detail."
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
- uses: actions/setup-node@v4
|
|
43
|
+
with:
|
|
44
|
+
node-version: 22
|
|
45
|
+
|
|
46
|
+
- name: Count onboarded repos
|
|
47
|
+
id: coverage
|
|
48
|
+
env:
|
|
49
|
+
GH_TOKEN: ${{ secrets.REDLINE_ORG_READ_TOKEN }}
|
|
50
|
+
SOURCE: ${{ vars.REDLINE_SOURCE || format('{0}/redline', github.repository_owner) }}
|
|
51
|
+
run: |
|
|
52
|
+
set -euo pipefail
|
|
53
|
+
# registry.json is the derived register of onboarded repositories, refreshed
|
|
54
|
+
# nightly by the source repo's Redline Registry workflow. Coverage is
|
|
55
|
+
# instrumented-vs-onboarded, so partial coverage cannot read as health. A
|
|
56
|
+
# failed read omits the figure rather than reporting zero — absent is honest,
|
|
57
|
+
# zero is a lie that looks like a finding.
|
|
58
|
+
# Written to a file rather than counted here: the dashboard reads the whole
|
|
59
|
+
# register for the enforcement ladder, not just its length, and a count
|
|
60
|
+
# alone cannot say how much of the estate is actually enforcing.
|
|
61
|
+
if gh api "repos/$SOURCE/contents/registry.json" --jq '.content' 2>/dev/null | base64 -d > registry.json; then
|
|
62
|
+
echo "found=true" >> "$GITHUB_OUTPUT"
|
|
63
|
+
else
|
|
64
|
+
rm -f registry.json
|
|
65
|
+
echo "found=false" >> "$GITHUB_OUTPUT"
|
|
66
|
+
echo "::warning::Could not read registry.json from $SOURCE — coverage and the ladder will be omitted."
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# No checkout of the Redline source, and no copy of its scripts in this
|
|
70
|
+
# repository. The command ships in the package; this repo owns its data and
|
|
71
|
+
# nothing else.
|
|
72
|
+
- name: Build dashboard
|
|
73
|
+
env:
|
|
74
|
+
STANDARDS_VERSION: ${{ vars.STANDARDS_VERSION }}
|
|
75
|
+
run: |
|
|
76
|
+
npx --yes "redlinegate@0.0.1" metrics dashboard \
|
|
77
|
+
--org "${{ github.repository_owner }}" \
|
|
78
|
+
--data data \
|
|
79
|
+
--days 90 \
|
|
80
|
+
--out dist \
|
|
81
|
+
--registry registry.json
|
|
82
|
+
|
|
83
|
+
- uses: actions/upload-pages-artifact@v3
|
|
84
|
+
with:
|
|
85
|
+
path: dist
|
|
86
|
+
|
|
87
|
+
deploy:
|
|
88
|
+
needs: build
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
environment:
|
|
91
|
+
name: github-pages
|
|
92
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
93
|
+
steps:
|
|
94
|
+
- id: deployment
|
|
95
|
+
uses: actions/deploy-pages@v4
|
|
96
|
+
|
|
97
|
+
alert:
|
|
98
|
+
needs: [build, deploy]
|
|
99
|
+
if: failure()
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
permissions:
|
|
102
|
+
contents: read
|
|
103
|
+
issues: write
|
|
104
|
+
steps:
|
|
105
|
+
- name: Open or update a failure issue
|
|
106
|
+
env:
|
|
107
|
+
GH_TOKEN: ${{ github.token }}
|
|
108
|
+
REPO: ${{ github.repository }}
|
|
109
|
+
RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
110
|
+
run: |
|
|
111
|
+
set -euo pipefail
|
|
112
|
+
title="Redline dashboard build is failing"
|
|
113
|
+
existing=$(gh issue list --repo "$REPO" --state open --search "$title in:title" --json number --jq '.[0].number // ""')
|
|
114
|
+
if [[ -n "$existing" ]]; then
|
|
115
|
+
gh issue comment "$existing" --repo "$REPO" --body "Still failing: $RUN"
|
|
116
|
+
else
|
|
117
|
+
gh issue create --repo "$REPO" --title "$title" \
|
|
118
|
+
--body "The dashboard build failed, so the published page is now stale. Run: $RUN"
|
|
119
|
+
fi
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Lives in the Redline source repo. Rebuilds the org-wide PR inbox on a schedule and
|
|
2
|
+
# publishes it to GitHub Pages.
|
|
3
|
+
#
|
|
4
|
+
# SECURITY: the page lists PR titles, authors and repo names. Set the Pages site to
|
|
5
|
+
# private or internal visibility (Settings > Pages > Visibility) BEFORE enabling this.
|
|
6
|
+
# On a public Pages site this publishes internal delivery detail to the internet. The
|
|
7
|
+
# build refuses to run until PAGES_VISIBILITY_ACKNOWLEDGED is set as a repo variable.
|
|
8
|
+
name: Redline Inbox
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
schedule:
|
|
12
|
+
- cron: '*/30 6-19 * * 1-5'
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
pages: write
|
|
18
|
+
id-token: write
|
|
19
|
+
|
|
20
|
+
concurrency:
|
|
21
|
+
group: inbox
|
|
22
|
+
cancel-in-progress: true
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
build:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
timeout-minutes: 15
|
|
28
|
+
steps:
|
|
29
|
+
- name: Confirm Pages visibility was reviewed
|
|
30
|
+
env:
|
|
31
|
+
ACK: ${{ vars.PAGES_VISIBILITY_ACKNOWLEDGED }}
|
|
32
|
+
run: |
|
|
33
|
+
if [[ "${ACK:-}" != "private" && "${ACK:-}" != "internal" ]]; then
|
|
34
|
+
echo "::error::Set the repository variable PAGES_VISIBILITY_ACKNOWLEDGED to 'private' or 'internal' after confirming the Pages site is not public. This page exposes org-wide PR titles and authors."
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
- uses: actions/setup-node@v4
|
|
40
|
+
with:
|
|
41
|
+
node-version: 22
|
|
42
|
+
|
|
43
|
+
- name: Install and build
|
|
44
|
+
run: |
|
|
45
|
+
npm ci
|
|
46
|
+
npm run build
|
|
47
|
+
|
|
48
|
+
# This one runs in the source repo, so it uses the build it is about to
|
|
49
|
+
# ship rather than the last published package: a broken inbox here is a
|
|
50
|
+
# broken command, and finding that out from the release is too late.
|
|
51
|
+
- name: Build inbox
|
|
52
|
+
env:
|
|
53
|
+
GH_TOKEN: ${{ secrets.REDLINE_ORG_READ_TOKEN }}
|
|
54
|
+
run: |
|
|
55
|
+
node dist/bin/redline.js metrics inbox \
|
|
56
|
+
--org "${{ github.repository_owner }}" \
|
|
57
|
+
--out dist
|
|
58
|
+
|
|
59
|
+
- uses: actions/upload-pages-artifact@v3
|
|
60
|
+
with:
|
|
61
|
+
path: dist
|
|
62
|
+
|
|
63
|
+
deploy:
|
|
64
|
+
needs: build
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
environment:
|
|
67
|
+
name: github-pages
|
|
68
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
69
|
+
steps:
|
|
70
|
+
- id: deployment
|
|
71
|
+
uses: actions/deploy-pages@v4
|
|
72
|
+
|
|
73
|
+
# A silently stale inbox is worse than no inbox: people trust a page that stopped
|
|
74
|
+
# updating three weeks ago. Surface the failure where someone will see it.
|
|
75
|
+
alert:
|
|
76
|
+
needs: [build, deploy]
|
|
77
|
+
if: failure()
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
permissions:
|
|
80
|
+
contents: read
|
|
81
|
+
issues: write
|
|
82
|
+
steps:
|
|
83
|
+
- name: Open or update a failure issue
|
|
84
|
+
env:
|
|
85
|
+
GH_TOKEN: ${{ github.token }}
|
|
86
|
+
REPO: ${{ github.repository }}
|
|
87
|
+
RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
88
|
+
run: |
|
|
89
|
+
set -euo pipefail
|
|
90
|
+
title="Redline inbox build is failing"
|
|
91
|
+
existing=$(gh issue list --repo "$REPO" --state open --search "$title in:title" --json number --jq '.[0].number // ""')
|
|
92
|
+
if [[ -n "$existing" ]]; then
|
|
93
|
+
gh issue comment "$existing" --repo "$REPO" --body "Still failing: $RUN"
|
|
94
|
+
else
|
|
95
|
+
gh issue create --repo "$REPO" --title "$title" \
|
|
96
|
+
--body "The scheduled inbox build failed. The published page is now stale. Run: $RUN"
|
|
97
|
+
fi
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Lives in the redline-metrics repo. Pulls review outcomes for merged PRs across the org
|
|
2
|
+
# and commits them as monthly JSONL.
|
|
3
|
+
#
|
|
4
|
+
# Replaces the old per-repo telemetry workflow: no Redline secret is stored in any
|
|
5
|
+
# product repo, so onboarding a repo grants Redline no write access to anything.
|
|
6
|
+
name: Redline Collect
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: '0 5 * * *'
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
days:
|
|
14
|
+
description: Look-back window in days
|
|
15
|
+
type: string
|
|
16
|
+
default: '8'
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: write
|
|
20
|
+
|
|
21
|
+
concurrency:
|
|
22
|
+
group: redline-collect
|
|
23
|
+
cancel-in-progress: false
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
collect:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
timeout-minutes: 30
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- uses: actions/setup-node@v4
|
|
32
|
+
with:
|
|
33
|
+
node-version: 22
|
|
34
|
+
|
|
35
|
+
- name: Collect telemetry
|
|
36
|
+
env:
|
|
37
|
+
# Read-only: repo metadata + pull requests across the org. No write scope.
|
|
38
|
+
# The token travels as an environment variable rather than a flag: a
|
|
39
|
+
# command line is visible in the process table.
|
|
40
|
+
GH_TOKEN: ${{ secrets.REDLINE_ORG_READ_TOKEN }}
|
|
41
|
+
run: |
|
|
42
|
+
npx --yes "redlinegate@0.0.1" metrics collect \
|
|
43
|
+
--org "${{ github.repository_owner }}" \
|
|
44
|
+
--days "${{ inputs.days || '8' }}" \
|
|
45
|
+
--out data
|
|
46
|
+
|
|
47
|
+
- name: Commit
|
|
48
|
+
run: |
|
|
49
|
+
set -euo pipefail
|
|
50
|
+
if git diff --quiet -- data; then
|
|
51
|
+
echo "no telemetry changes" >> "$GITHUB_STEP_SUMMARY"
|
|
52
|
+
exit 0
|
|
53
|
+
fi
|
|
54
|
+
git config user.name "redline-bot"
|
|
55
|
+
git config user.email "redline-bot@users.noreply.github.com"
|
|
56
|
+
git add data
|
|
57
|
+
git commit -m "data: telemetry through $(date -u +%Y-%m-%d)"
|
|
58
|
+
# Another run (or a digest commit) may have landed since checkout.
|
|
59
|
+
git pull --rebase origin "${GITHUB_REF_NAME}"
|
|
60
|
+
git push origin "HEAD:${GITHUB_REF_NAME}"
|
|
61
|
+
git diff --stat HEAD~1 -- data >> "$GITHUB_STEP_SUMMARY"
|