peer-ai-standards 1.0.0-next.0
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 +62 -0
- package/dist/core/ai-features.d.ts +65 -0
- package/dist/core/ai-features.js +113 -0
- package/dist/core/api-design.d.ts +41 -0
- package/dist/core/api-design.js +91 -0
- package/dist/core/architecture.d.ts +41 -0
- package/dist/core/architecture.js +93 -0
- package/dist/core/backend.d.ts +21 -0
- package/dist/core/backend.js +25 -0
- package/dist/core/code-quality.d.ts +91 -0
- package/dist/core/code-quality.js +179 -0
- package/dist/core/data.d.ts +45 -0
- package/dist/core/data.js +59 -0
- package/dist/core/delivery.d.ts +153 -0
- package/dist/core/delivery.js +149 -0
- package/dist/core/design-accessibility.d.ts +124 -0
- package/dist/core/design-accessibility.js +199 -0
- package/dist/core/frontend.d.ts +77 -0
- package/dist/core/frontend.js +109 -0
- package/dist/core/mobile.d.ts +46 -0
- package/dist/core/mobile.js +83 -0
- package/dist/core/money.d.ts +81 -0
- package/dist/core/money.js +135 -0
- package/dist/core/operations.d.ts +108 -0
- package/dist/core/operations.js +177 -0
- package/dist/core/performance.d.ts +53 -0
- package/dist/core/performance.js +85 -0
- package/dist/core/privacy-compliance.d.ts +68 -0
- package/dist/core/privacy-compliance.js +77 -0
- package/dist/core/reliability.d.ts +67 -0
- package/dist/core/reliability.js +105 -0
- package/dist/core/requirements.d.ts +41 -0
- package/dist/core/requirements.js +58 -0
- package/dist/core/safety-critical.d.ts +41 -0
- package/dist/core/safety-critical.js +71 -0
- package/dist/core/security.d.ts +281 -0
- package/dist/core/security.js +427 -0
- package/dist/core/system-design.d.ts +31 -0
- package/dist/core/system-design.js +69 -0
- package/dist/core/testing.d.ts +51 -0
- package/dist/core/testing.js +124 -0
- package/dist/domains.d.ts +6 -0
- package/dist/domains.js +53 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +118 -0
- package/dist/profile.d.ts +262 -0
- package/dist/profile.js +269 -0
- package/dist/profiles/express.d.ts +2 -0
- package/dist/profiles/express.js +93 -0
- package/dist/profiles/fastapi.d.ts +2 -0
- package/dist/profiles/fastapi.js +104 -0
- package/dist/profiles/fastify.d.ts +2 -0
- package/dist/profiles/fastify.js +56 -0
- package/dist/profiles/github-actions.d.ts +2 -0
- package/dist/profiles/github-actions.js +151 -0
- package/dist/profiles/nestjs.d.ts +2 -0
- package/dist/profiles/nestjs.js +77 -0
- package/dist/profiles/next.d.ts +2 -0
- package/dist/profiles/next.js +73 -0
- package/dist/profiles/node.d.ts +2 -0
- package/dist/profiles/node.js +79 -0
- package/dist/profiles/python.d.ts +2 -0
- package/dist/profiles/python.js +232 -0
- package/dist/profiles/react-native.d.ts +2 -0
- package/dist/profiles/react-native.js +133 -0
- package/dist/profiles/react.d.ts +2 -0
- package/dist/profiles/react.js +180 -0
- package/dist/profiles/typescript.d.ts +2 -0
- package/dist/profiles/typescript.js +214 -0
- package/dist/rule.d.ts +72 -0
- package/dist/rule.js +39 -0
- package/package.json +39 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// What makes code good in any language: naming, size, duplication, errors and types.
|
|
2
|
+
export const codeQuality = [
|
|
3
|
+
{
|
|
4
|
+
id: "CODE-01",
|
|
5
|
+
domain: "code-quality",
|
|
6
|
+
title: "Names say what things are",
|
|
7
|
+
rule: "A name says what the thing is, in the language's own style: `amountMinor` or `amount_minor`, not `amt`; `profileId` or `profile_id`, not `pid`.",
|
|
8
|
+
why: "Code is read far more often than it's written. An abbreviation saves the writer a second and costs every reader a guess.",
|
|
9
|
+
ask: "Could someone new to the code understand every name in this change without asking?",
|
|
10
|
+
stage: "prototype",
|
|
11
|
+
check: "ai-review",
|
|
12
|
+
severity: "low",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: "CODE-02",
|
|
16
|
+
domain: "code-quality",
|
|
17
|
+
title: "True-or-false values read as statements",
|
|
18
|
+
rule: "A true-or-false value is named as a statement, such as `isPublished`, `hasError` or `canBook` (or `is_published` where the language uses snake_case).",
|
|
19
|
+
why: "`published` could mean a date, a flag or a count; `isPublished` can only mean one thing.",
|
|
20
|
+
ask: "Does every true-or-false value in this change read as a statement?",
|
|
21
|
+
stage: "prototype",
|
|
22
|
+
check: "ai-review",
|
|
23
|
+
severity: "low",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "CODE-03",
|
|
27
|
+
domain: "code-quality",
|
|
28
|
+
title: "Things are named the way the people using the product name them",
|
|
29
|
+
rule: "Code, screens and design tokens use the words the people using the product use: a person manages notifications, not webhook config.",
|
|
30
|
+
why: "When the code and the product use different words, every conversation needs a translator, and mistakes hide in the translation.",
|
|
31
|
+
ask: "Do the names in this change match the words on the screen and in the requirements?",
|
|
32
|
+
stage: "prototype",
|
|
33
|
+
check: "ai-review",
|
|
34
|
+
severity: "low",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "CODE-04",
|
|
38
|
+
domain: "code-quality",
|
|
39
|
+
title: "Rule of three",
|
|
40
|
+
rule: "Copy code freely once, note it the second time, and move it into one shared place the third time.",
|
|
41
|
+
why: "A shared piece built too early is harder to remove than three similar ones, because everything comes to depend on it.",
|
|
42
|
+
ask: "Is anything in this change repeated for the third time, or shared before it was needed?",
|
|
43
|
+
stage: "mvp",
|
|
44
|
+
check: "ai-review",
|
|
45
|
+
severity: "low",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "CODE-05",
|
|
49
|
+
domain: "code-quality",
|
|
50
|
+
title: "Rules that must never disagree are shared on the first repeat",
|
|
51
|
+
rule: "Money maths, validation, permission checks and safety-critical logic are moved into one shared place the first time they're repeated, not the third.",
|
|
52
|
+
why: "Two copies of a rule eventually disagree. When the rule is money, safety or who may see what, the disagreement is a wrong charge, a harmed person or a data leak.",
|
|
53
|
+
ask: "Is any money, validation, permission or safety logic written more than once?",
|
|
54
|
+
stage: "prototype",
|
|
55
|
+
check: "ai-review",
|
|
56
|
+
severity: "high",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "CODE-06",
|
|
60
|
+
domain: "code-quality",
|
|
61
|
+
title: "A deliberate copy names its twin",
|
|
62
|
+
rule: "If a rule truly has to live in two places, each copy says where the other one is.",
|
|
63
|
+
why: "Copies drift apart silently when nobody knows the other exists.",
|
|
64
|
+
ask: "Does every deliberate copy of logic point to its twin?",
|
|
65
|
+
stage: "mvp",
|
|
66
|
+
check: "ai-review",
|
|
67
|
+
severity: "medium",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "CODE-07",
|
|
71
|
+
domain: "code-quality",
|
|
72
|
+
title: "A function does one thing",
|
|
73
|
+
rule: "A function has one reason to change.",
|
|
74
|
+
why: "A function that does two things can't change one of them without risking the other, and its tests have to cover both.",
|
|
75
|
+
ask: "Does each function this change touches do one thing?",
|
|
76
|
+
stage: "mvp",
|
|
77
|
+
check: "ai-review",
|
|
78
|
+
severity: "medium",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "CODE-08",
|
|
82
|
+
domain: "code-quality",
|
|
83
|
+
title: "Comments explain why; the code explains what",
|
|
84
|
+
rule: "If code needs a comment to explain what it does, it's too long or badly named. Comments that explain why are welcome.",
|
|
85
|
+
why: "Comments about what code does go out of date when the code changes. The reasons behind it last.",
|
|
86
|
+
ask: "Does any comment in this change explain what the code does, rather than why?",
|
|
87
|
+
stage: "mvp",
|
|
88
|
+
check: "ai-review",
|
|
89
|
+
severity: "low",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "CODE-09",
|
|
93
|
+
domain: "code-quality",
|
|
94
|
+
title: "Deep nesting becomes early returns",
|
|
95
|
+
rule: "When conditions nest deeply, handle the simple cases first and return, so the main path reads straight down. Each profile sets how deep is too deep.",
|
|
96
|
+
why: "Every level of nesting is one more thing a reader has to hold in mind.",
|
|
97
|
+
ask: "Is any code nested more deeply than its profile allows?",
|
|
98
|
+
stage: "mvp",
|
|
99
|
+
check: "auto",
|
|
100
|
+
severity: "low",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: "CODE-10",
|
|
104
|
+
domain: "code-quality",
|
|
105
|
+
title: "Size prompts a question",
|
|
106
|
+
rule: "A function, component or module that grows past its profile's size limit prompts a question: is it doing two things, and what could move out? Size alone isn't a defect.",
|
|
107
|
+
why: "Large units usually hide a second job, and the limit is the reminder to look for it.",
|
|
108
|
+
ask: "Has anything grown past its size limit, and has someone asked whether it's doing two things?",
|
|
109
|
+
stage: "mvp",
|
|
110
|
+
check: "auto",
|
|
111
|
+
severity: "low",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: "CODE-11",
|
|
115
|
+
domain: "code-quality",
|
|
116
|
+
title: "No swallowed errors",
|
|
117
|
+
rule: "An error is never caught and ignored. Where ignoring one is genuinely right, such as cleanup that mustn't fail the work it cleans up after, it's logged, and the reason is written beside it.",
|
|
118
|
+
why: "A swallowed error turns a loud, fixable failure into silent wrong behaviour that surfaces weeks later.",
|
|
119
|
+
ask: "Is any error caught and dropped without being logged and explained?",
|
|
120
|
+
stage: "prototype",
|
|
121
|
+
check: "auto",
|
|
122
|
+
severity: "high",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: "CODE-12",
|
|
126
|
+
domain: "code-quality",
|
|
127
|
+
title: "Catching every kind of error needs a reason",
|
|
128
|
+
rule: "Catching every kind of error at once needs a comment saying what's expected and why it's safe to handle them all the same way.",
|
|
129
|
+
why: "A catch-all also catches the bugs nobody expected, and hides them.",
|
|
130
|
+
ask: "Does every catch-all in this change say what it expects and why?",
|
|
131
|
+
stage: "mvp",
|
|
132
|
+
check: "auto",
|
|
133
|
+
severity: "medium",
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: "CODE-13",
|
|
137
|
+
domain: "code-quality",
|
|
138
|
+
title: "Impossible states can't be written down",
|
|
139
|
+
rule: "When something has distinct states, such as loading, failed and ready, it's one status value, not several true-or-false flags that can contradict each other.",
|
|
140
|
+
why: "Three flags allow eight combinations, and most of them make no sense. One status allows only the real ones.",
|
|
141
|
+
ask: "Could any combination of flags in this change describe a state that can't really happen?",
|
|
142
|
+
stage: "mvp",
|
|
143
|
+
check: "ai-review",
|
|
144
|
+
severity: "medium",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: "CODE-14",
|
|
148
|
+
domain: "code-quality",
|
|
149
|
+
title: "Types are strict",
|
|
150
|
+
rule: "Where the language has types, they're strict. No escape-hatch type, such as TypeScript's `any` or Python's `Any`, where a real type exists: data of unknown shape is checked and narrowed.",
|
|
151
|
+
why: "An escape-hatch type switches the checks off exactly where the data is least trusted.",
|
|
152
|
+
ask: "Does this change use an escape-hatch type where a real type exists?",
|
|
153
|
+
stage: "prototype",
|
|
154
|
+
check: "auto",
|
|
155
|
+
severity: "medium",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
id: "CODE-15",
|
|
159
|
+
domain: "code-quality",
|
|
160
|
+
title: "Edge cases are handled",
|
|
161
|
+
rule: "Code gives the right answer at the edges of what it can receive: time zones and daylight saving, empty and very long input, ties and equal values, the first and last item, and zero.",
|
|
162
|
+
why: "Most bugs live at the edges. The ordinary path is the one everyone tries, so it's rarely where things break.",
|
|
163
|
+
ask: "Does this change give the right answer at its edges: time zones, empty or huge input, ties, first and last, and zero?",
|
|
164
|
+
stage: "mvp",
|
|
165
|
+
check: "ai-review",
|
|
166
|
+
severity: "medium",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: "CODE-16",
|
|
170
|
+
domain: "code-quality",
|
|
171
|
+
title: "The framework's own rules are kept",
|
|
172
|
+
rule: "Where a framework needs code written a certain way to work, such as React's rules for hooks, that way is followed, and checked by a tool where one exists.",
|
|
173
|
+
why: "A framework's rules protect assumptions the types can't see. Breaking one gives bugs that appear far from their cause, often only sometimes.",
|
|
174
|
+
ask: "Does this change break a rule its framework depends on?",
|
|
175
|
+
stage: "prototype",
|
|
176
|
+
check: "ai-review",
|
|
177
|
+
severity: "medium",
|
|
178
|
+
},
|
|
179
|
+
];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const data: ({
|
|
2
|
+
id: string;
|
|
3
|
+
domain: "data";
|
|
4
|
+
title: string;
|
|
5
|
+
rule: string;
|
|
6
|
+
why: string;
|
|
7
|
+
ask: string;
|
|
8
|
+
stage: "mvp";
|
|
9
|
+
check: "auto";
|
|
10
|
+
severity: "high";
|
|
11
|
+
when?: never;
|
|
12
|
+
} | {
|
|
13
|
+
id: string;
|
|
14
|
+
domain: "data";
|
|
15
|
+
title: string;
|
|
16
|
+
rule: string;
|
|
17
|
+
why: string;
|
|
18
|
+
ask: string;
|
|
19
|
+
stage: "prototype";
|
|
20
|
+
check: "ai-review";
|
|
21
|
+
severity: "critical";
|
|
22
|
+
when?: never;
|
|
23
|
+
} | {
|
|
24
|
+
id: string;
|
|
25
|
+
domain: "data";
|
|
26
|
+
title: string;
|
|
27
|
+
rule: string;
|
|
28
|
+
why: string;
|
|
29
|
+
ask: string;
|
|
30
|
+
stage: "mvp";
|
|
31
|
+
check: "ai-review";
|
|
32
|
+
severity: "medium";
|
|
33
|
+
when: "uploads"[];
|
|
34
|
+
} | {
|
|
35
|
+
id: string;
|
|
36
|
+
domain: "data";
|
|
37
|
+
title: string;
|
|
38
|
+
rule: string;
|
|
39
|
+
why: string;
|
|
40
|
+
ask: string;
|
|
41
|
+
stage: "mvp";
|
|
42
|
+
check: "auto";
|
|
43
|
+
severity: "medium";
|
|
44
|
+
when?: never;
|
|
45
|
+
})[];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Databases, migrations, stored files, and data kept on a person's device.
|
|
2
|
+
export const data = [
|
|
3
|
+
{
|
|
4
|
+
id: "DATA-01",
|
|
5
|
+
domain: "data",
|
|
6
|
+
title: "Migrations are the only source of truth for the database's structure",
|
|
7
|
+
rule: "The database's structure comes only from migrations. Tools that shape a database straight from the code are for experiments, never for a database that matters.",
|
|
8
|
+
why: "Those tools can't produce everything a migration can, such as triggers or partial indexes, and they can drop data without asking.",
|
|
9
|
+
ask: "Does this change shape a real database any way other than a migration?",
|
|
10
|
+
stage: "mvp",
|
|
11
|
+
check: "auto",
|
|
12
|
+
severity: "high",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: "DATA-02",
|
|
16
|
+
domain: "data",
|
|
17
|
+
title: "A model change ships with its migration",
|
|
18
|
+
rule: "A change to how data is modelled ships with its migration, in the same pull request, and CI checks that they match.",
|
|
19
|
+
why: "A model without its migration works on the developer's machine and fails everywhere else.",
|
|
20
|
+
ask: "Does every model change in this change come with its migration?",
|
|
21
|
+
stage: "mvp",
|
|
22
|
+
check: "auto",
|
|
23
|
+
severity: "high",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "DATA-03",
|
|
27
|
+
domain: "data",
|
|
28
|
+
title: "A change to stored data never loses it",
|
|
29
|
+
rule: "A migration or app update keeps existing data. Renaming or reshaping moves the data across. A table, column or storage key is removed only after its data has moved and nothing reads it: add, migrate, then remove. This includes data stored on a person's device.",
|
|
30
|
+
why: "Lost data can't be fixed by the next release. It's gone, along with the trust of everyone who lost it.",
|
|
31
|
+
ask: "Does this change remove, rename or reshape stored data without moving what's already there?",
|
|
32
|
+
stage: "prototype",
|
|
33
|
+
check: "ai-review",
|
|
34
|
+
severity: "critical",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "DATA-04",
|
|
38
|
+
domain: "data",
|
|
39
|
+
title: "Deleting a record deletes its files",
|
|
40
|
+
rule: "When a record is deleted, the files that belong to it are deleted too.",
|
|
41
|
+
why: "Orphaned files keep personal data long after the person asked for it to go, and cost money to store.",
|
|
42
|
+
ask: "Does deleting a record in this change also delete its files?",
|
|
43
|
+
stage: "mvp",
|
|
44
|
+
check: "ai-review",
|
|
45
|
+
severity: "medium",
|
|
46
|
+
when: ["uploads"],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "DATA-05",
|
|
50
|
+
domain: "data",
|
|
51
|
+
title: "Export and import round-trip exactly",
|
|
52
|
+
rule: "Where the product offers export and import, importing an export gives back exactly what was exported, and a test proves it.",
|
|
53
|
+
why: "An export people can't restore from exactly is a backup that fails on the day it's needed.",
|
|
54
|
+
ask: "If this change affects export or import, does a test prove they still round-trip exactly?",
|
|
55
|
+
stage: "mvp",
|
|
56
|
+
check: "auto",
|
|
57
|
+
severity: "medium",
|
|
58
|
+
},
|
|
59
|
+
];
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
export declare const delivery: ({
|
|
2
|
+
id: string;
|
|
3
|
+
domain: "delivery";
|
|
4
|
+
title: string;
|
|
5
|
+
rule: string;
|
|
6
|
+
why: string;
|
|
7
|
+
ask: string;
|
|
8
|
+
stage: "prototype";
|
|
9
|
+
check: "auto";
|
|
10
|
+
severity: "medium";
|
|
11
|
+
sources?: never;
|
|
12
|
+
} | {
|
|
13
|
+
id: string;
|
|
14
|
+
domain: "delivery";
|
|
15
|
+
title: string;
|
|
16
|
+
rule: string;
|
|
17
|
+
why: string;
|
|
18
|
+
ask: string;
|
|
19
|
+
stage: "mvp";
|
|
20
|
+
check: "ai-review";
|
|
21
|
+
severity: "low";
|
|
22
|
+
sources?: never;
|
|
23
|
+
} | {
|
|
24
|
+
id: string;
|
|
25
|
+
domain: "delivery";
|
|
26
|
+
title: string;
|
|
27
|
+
rule: string;
|
|
28
|
+
why: string;
|
|
29
|
+
ask: string;
|
|
30
|
+
stage: "mvp";
|
|
31
|
+
check: "auto";
|
|
32
|
+
severity: "high";
|
|
33
|
+
sources: {
|
|
34
|
+
name: string;
|
|
35
|
+
ref: string;
|
|
36
|
+
url: string;
|
|
37
|
+
}[];
|
|
38
|
+
} | {
|
|
39
|
+
id: string;
|
|
40
|
+
domain: "delivery";
|
|
41
|
+
title: string;
|
|
42
|
+
rule: string;
|
|
43
|
+
why: string;
|
|
44
|
+
ask: string;
|
|
45
|
+
stage: "mvp";
|
|
46
|
+
check: "auto";
|
|
47
|
+
severity: "high";
|
|
48
|
+
sources?: never;
|
|
49
|
+
} | {
|
|
50
|
+
id: string;
|
|
51
|
+
domain: "delivery";
|
|
52
|
+
title: string;
|
|
53
|
+
rule: string;
|
|
54
|
+
why: string;
|
|
55
|
+
ask: string;
|
|
56
|
+
stage: "mvp";
|
|
57
|
+
check: "auto";
|
|
58
|
+
severity: "medium";
|
|
59
|
+
sources?: never;
|
|
60
|
+
} | {
|
|
61
|
+
id: string;
|
|
62
|
+
domain: "delivery";
|
|
63
|
+
title: string;
|
|
64
|
+
rule: string;
|
|
65
|
+
why: string;
|
|
66
|
+
ask: string;
|
|
67
|
+
stage: "mvp";
|
|
68
|
+
check: "ai-review";
|
|
69
|
+
severity: "high";
|
|
70
|
+
sources?: never;
|
|
71
|
+
} | {
|
|
72
|
+
id: string;
|
|
73
|
+
domain: "delivery";
|
|
74
|
+
title: string;
|
|
75
|
+
rule: string;
|
|
76
|
+
why: string;
|
|
77
|
+
ask: string;
|
|
78
|
+
stage: "production";
|
|
79
|
+
check: "ai-review";
|
|
80
|
+
severity: "medium";
|
|
81
|
+
sources: {
|
|
82
|
+
name: string;
|
|
83
|
+
ref: string;
|
|
84
|
+
url: string;
|
|
85
|
+
}[];
|
|
86
|
+
} | {
|
|
87
|
+
id: string;
|
|
88
|
+
domain: "delivery";
|
|
89
|
+
title: string;
|
|
90
|
+
rule: string;
|
|
91
|
+
why: string;
|
|
92
|
+
ask: string;
|
|
93
|
+
stage: "production";
|
|
94
|
+
check: "auto";
|
|
95
|
+
severity: "medium";
|
|
96
|
+
sources?: never;
|
|
97
|
+
} | {
|
|
98
|
+
id: string;
|
|
99
|
+
domain: "delivery";
|
|
100
|
+
title: string;
|
|
101
|
+
rule: string;
|
|
102
|
+
why: string;
|
|
103
|
+
ask: string;
|
|
104
|
+
stage: "mvp";
|
|
105
|
+
check: "ai-review";
|
|
106
|
+
severity: "high";
|
|
107
|
+
sources: {
|
|
108
|
+
name: string;
|
|
109
|
+
ref: string;
|
|
110
|
+
url: string;
|
|
111
|
+
}[];
|
|
112
|
+
} | {
|
|
113
|
+
id: string;
|
|
114
|
+
domain: "delivery";
|
|
115
|
+
title: string;
|
|
116
|
+
rule: string;
|
|
117
|
+
why: string;
|
|
118
|
+
ask: string;
|
|
119
|
+
stage: "production";
|
|
120
|
+
check: "auto";
|
|
121
|
+
severity: "medium";
|
|
122
|
+
sources: {
|
|
123
|
+
name: string;
|
|
124
|
+
ref: string;
|
|
125
|
+
url: string;
|
|
126
|
+
}[];
|
|
127
|
+
} | {
|
|
128
|
+
id: string;
|
|
129
|
+
domain: "delivery";
|
|
130
|
+
title: string;
|
|
131
|
+
rule: string;
|
|
132
|
+
why: string;
|
|
133
|
+
ask: string;
|
|
134
|
+
stage: "mvp";
|
|
135
|
+
check: "ai-review";
|
|
136
|
+
severity: "medium";
|
|
137
|
+
sources?: never;
|
|
138
|
+
} | {
|
|
139
|
+
id: string;
|
|
140
|
+
domain: "delivery";
|
|
141
|
+
title: string;
|
|
142
|
+
rule: string;
|
|
143
|
+
why: string;
|
|
144
|
+
ask: string;
|
|
145
|
+
stage: "production";
|
|
146
|
+
check: "ai-review";
|
|
147
|
+
severity: "high";
|
|
148
|
+
sources: {
|
|
149
|
+
name: string;
|
|
150
|
+
ref: string;
|
|
151
|
+
url: string;
|
|
152
|
+
}[];
|
|
153
|
+
})[];
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Dependencies, the pipeline every change goes through, and how changes reach people.
|
|
2
|
+
const ASVS = "OWASP ASVS 5.0";
|
|
3
|
+
const V15 = "https://github.com/OWASP/ASVS/blob/master/5.0/en/0x24-V15-Secure-Coding-and-Architecture.md";
|
|
4
|
+
const MASVS = "OWASP MASVS 2.1.0";
|
|
5
|
+
export const delivery = [
|
|
6
|
+
{
|
|
7
|
+
id: "DEL-01",
|
|
8
|
+
domain: "delivery",
|
|
9
|
+
title: "Versions are pinned and the lockfile is committed",
|
|
10
|
+
rule: 'Every dependency names the exact version that was tested, never "latest", and the lockfile is committed.',
|
|
11
|
+
why: '"Whatever is newest today" isn\'t a version. A build that pulls in different code tomorrow can break, or be compromised, without anyone changing a line.',
|
|
12
|
+
ask: "Does this change add a dependency without an exact version, or leave the lockfile out?",
|
|
13
|
+
stage: "prototype",
|
|
14
|
+
check: "auto",
|
|
15
|
+
severity: "medium",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "DEL-02",
|
|
19
|
+
domain: "delivery",
|
|
20
|
+
title: "A new dependency is justified",
|
|
21
|
+
rule: "A new dependency comes with a reason in the pull request: what it does, why nothing already there does it, and what it brings with it.",
|
|
22
|
+
why: "Every dependency is code you didn't write and have to trust, update and secure for as long as you use it.",
|
|
23
|
+
ask: "Does every new dependency in this change say why it's needed?",
|
|
24
|
+
stage: "mvp",
|
|
25
|
+
check: "ai-review",
|
|
26
|
+
severity: "low",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "DEL-03",
|
|
30
|
+
domain: "delivery",
|
|
31
|
+
title: "Dependencies are watched for vulnerabilities, and each is fixed in a set time",
|
|
32
|
+
rule: "Dependencies are checked for known vulnerabilities on every change and at least daily, and each vulnerability is fixed within a set time for its severity.",
|
|
33
|
+
why: "Most attacks on software use vulnerabilities that were already public, in components nobody updated. New ones are published every day about code that's already running, so checking only when something changes misses them.",
|
|
34
|
+
ask: "Does this change leave a dependency with a known vulnerability past its time to fix?",
|
|
35
|
+
stage: "mvp",
|
|
36
|
+
check: "auto",
|
|
37
|
+
severity: "high",
|
|
38
|
+
sources: [
|
|
39
|
+
{ name: ASVS, ref: "15.2.1, level 1", url: V15 },
|
|
40
|
+
{ name: MASVS, ref: "MASVS-CODE-3", url: "https://github.com/OWASP/masvs/blob/master/controls/MASVS-CODE-3.md" },
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "DEL-04",
|
|
45
|
+
domain: "delivery",
|
|
46
|
+
title: "Every change passes the same required checks before it merges",
|
|
47
|
+
rule: "Every change passes the same automated checks before it merges: formatting, linting, types, tests, secret scanning, dependency checks and code scanning. The checks are required, not advisory.",
|
|
48
|
+
why: "A check that can be skipped will be skipped, on the day it would have caught something.",
|
|
49
|
+
ask: "Does this change merge only after passing every required check?",
|
|
50
|
+
stage: "mvp",
|
|
51
|
+
check: "auto",
|
|
52
|
+
severity: "high",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "DEL-05",
|
|
56
|
+
domain: "delivery",
|
|
57
|
+
title: "No check only reports",
|
|
58
|
+
rule: "Every check in the pipeline fails the build when it finds a problem. None is set to report and carry on.",
|
|
59
|
+
why: "A check that reports without failing gives the same green as a clean pass, so nobody reads it.",
|
|
60
|
+
ask: "Is any check in this change set to report without failing the build?",
|
|
61
|
+
stage: "mvp",
|
|
62
|
+
check: "auto",
|
|
63
|
+
severity: "medium",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "DEL-06",
|
|
67
|
+
domain: "delivery",
|
|
68
|
+
title: "Changes reach production only through the pipeline",
|
|
69
|
+
rule: "Changes reach production only through the pipeline, never by hand from someone's computer.",
|
|
70
|
+
why: "A change made by hand skips every check, and nobody can say afterwards exactly what's running.",
|
|
71
|
+
ask: "Could any change in this project reach production without going through the pipeline?",
|
|
72
|
+
stage: "mvp",
|
|
73
|
+
check: "ai-review",
|
|
74
|
+
severity: "high",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: "DEL-07",
|
|
78
|
+
domain: "delivery",
|
|
79
|
+
title: "Only what's needed ships to production",
|
|
80
|
+
rule: "Production gets only what the product needs to run: no test code, sample code, development tools or debug features.",
|
|
81
|
+
why: "Every extra piece in production is something an attacker can find and use.",
|
|
82
|
+
ask: "Does this change ship test, sample or development code to production?",
|
|
83
|
+
stage: "production",
|
|
84
|
+
check: "ai-review",
|
|
85
|
+
severity: "medium",
|
|
86
|
+
sources: [{ name: ASVS, ref: "15.2.3, level 2", url: V15 }],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: "DEL-08",
|
|
90
|
+
domain: "delivery",
|
|
91
|
+
title: "The running app is scanned before it's released",
|
|
92
|
+
rule: "Before a release reaches production, a scanner tests the running app in staging from the outside, the way an attacker would. Every finding is fixed or recorded as an accepted risk. The scan runs only against the project's own staging, never production or anyone else's system.",
|
|
93
|
+
why: "Code scanning reads the code. It can't see a server that's set up wrongly, a debug page left switched on or a missing security header. Only testing the running app finds those.",
|
|
94
|
+
ask: "Was the running app scanned in staging before this release, and is every finding fixed or accepted?",
|
|
95
|
+
stage: "production",
|
|
96
|
+
check: "auto",
|
|
97
|
+
severity: "medium",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "DEL-09",
|
|
101
|
+
domain: "delivery",
|
|
102
|
+
title: "Packages come only from the registry you expect",
|
|
103
|
+
rule: "Every dependency, and everything it depends on, is installed from the registry the project expects. A name the project uses for its own private packages can't be served from a public registry instead.",
|
|
104
|
+
why: "If a private package's name is free on a public registry, anyone can publish a package under it with a higher version, and a build that looks in both places installs theirs. This is called dependency confusion.",
|
|
105
|
+
ask: "Could any dependency in this change be installed from a registry the project doesn't expect?",
|
|
106
|
+
stage: "mvp",
|
|
107
|
+
check: "ai-review",
|
|
108
|
+
severity: "high",
|
|
109
|
+
sources: [
|
|
110
|
+
{ name: ASVS, ref: "15.2.4, level 3", url: V15 },
|
|
111
|
+
{ name: ASVS, ref: "15.1.2, level 2", url: V15 },
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "DEL-10",
|
|
116
|
+
domain: "delivery",
|
|
117
|
+
title: "There's a current list of every dependency",
|
|
118
|
+
rule: "The project keeps a list of every dependency it ships, direct and indirect, with its version and where it comes from, such as a software bill of materials, and updates it with every release.",
|
|
119
|
+
why: "When a vulnerability is announced, the first question is whether you use the affected package. Without a list, answering takes days; with one, it's a search.",
|
|
120
|
+
ask: "Is the list of dependencies up to date for this release?",
|
|
121
|
+
stage: "production",
|
|
122
|
+
check: "auto",
|
|
123
|
+
severity: "medium",
|
|
124
|
+
sources: [{ name: ASVS, ref: "15.1.2, level 2", url: V15 }],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: "DEL-11",
|
|
128
|
+
domain: "delivery",
|
|
129
|
+
title: "Every dependency's licence allows how the product uses it",
|
|
130
|
+
rule: "Each dependency's licence is known and allows how the product is used and distributed. A licence that would require publishing the product's own code, or that forbids commercial use, needs a person's decision before the dependency is added.",
|
|
131
|
+
why: "A licence is a legal agreement. One that doesn't fit can force a product to publish its code or stop selling it, and it's cheapest to catch before the code depends on it.",
|
|
132
|
+
ask: "Does this change add a dependency whose licence doesn't fit how the product is used?",
|
|
133
|
+
stage: "mvp",
|
|
134
|
+
check: "ai-review",
|
|
135
|
+
severity: "medium",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "DEL-12",
|
|
139
|
+
domain: "delivery",
|
|
140
|
+
title: "Risky dependencies are chosen on purpose",
|
|
141
|
+
rule: "A dependency that runs code when it's installed, is no longer maintained, or has a name one slip away from a better-known package is checked before it's added, and kept only with a written reason.",
|
|
142
|
+
why: "Attackers take over abandoned packages and publish look-alike names, and a package that runs code when it's installed runs it on every developer's machine and every build.",
|
|
143
|
+
ask: "Does this change add a dependency that runs code when installed, is no longer maintained, or looks like another package's name?",
|
|
144
|
+
stage: "production",
|
|
145
|
+
check: "ai-review",
|
|
146
|
+
severity: "high",
|
|
147
|
+
sources: [{ name: ASVS, ref: "15.1.4, level 3", url: V15 }],
|
|
148
|
+
},
|
|
149
|
+
];
|