sinapse-ai 7.7.4 → 7.7.6
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/.claude/CLAUDE.md +1 -0
- package/.claude/rules/security-data-protection.md +184 -0
- package/.codex/delegation-matrix.json +401 -0
- package/.codex/handoff-packet.schema.json +68 -0
- package/.codex/scripts/resolve-codex-delegation-parity.js +205 -0
- package/.codex/scripts/resolve-codex-delegation.js +176 -0
- package/.codex/tasks/route-sinapse-request.md +7 -5
- package/.sinapse-ai/constitution.md +67 -1
- package/.sinapse-ai/core/doctor/checks/constitution-consistency.js +1 -0
- package/.sinapse-ai/core/health-check/checks/project/constitution-consistency.js +1 -0
- package/.sinapse-ai/data/entity-registry.yaml +793 -772
- package/.sinapse-ai/data/registry-update-log.jsonl +6 -0
- package/.sinapse-ai/infrastructure/scripts/validate-codex-delegation.js +294 -0
- package/.sinapse-ai/infrastructure/scripts/validate-codex-sync.js +3 -0
- package/.sinapse-ai/install-manifest.yaml +17 -13
- package/.sinapse-ai/product/templates/ide-rules/claude-rules.md +1 -0
- package/docs/codex-delegation-parity.md +115 -0
- package/docs/codex-parity-program.md +7 -0
- package/package.json +4 -1
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +7 -2
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
|
|
8
|
+
const MATRIX_PATH = path.join('.codex', 'delegation-parity.json');
|
|
9
|
+
|
|
10
|
+
function loadDelegationMatrix(projectRoot = PROJECT_ROOT) {
|
|
11
|
+
const matrixPath = path.join(projectRoot, MATRIX_PATH);
|
|
12
|
+
const raw = fs.readFileSync(matrixPath, 'utf8');
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function normalizeRouteInput(value) {
|
|
17
|
+
return String(value || '')
|
|
18
|
+
.trim()
|
|
19
|
+
.replace(/^[@*]/, '')
|
|
20
|
+
.toLowerCase();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function normalizeActorInput(value) {
|
|
24
|
+
return String(value || '')
|
|
25
|
+
.trim()
|
|
26
|
+
.replace(/^@/, '')
|
|
27
|
+
.toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function collectRouteAliases(routeId, routeSpec) {
|
|
31
|
+
return [routeId, ...(routeSpec.aliases || [])]
|
|
32
|
+
.map((alias) => normalizeRouteInput(alias))
|
|
33
|
+
.filter(Boolean);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveDelegationRoute(routeInput, projectRoot = PROJECT_ROOT, matrix = loadDelegationMatrix(projectRoot)) {
|
|
37
|
+
const normalized = normalizeRouteInput(routeInput);
|
|
38
|
+
const matches = Object.entries(matrix.routes || {}).filter(([routeId, routeSpec]) =>
|
|
39
|
+
collectRouteAliases(routeId, routeSpec).includes(normalized),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (matches.length > 1) {
|
|
43
|
+
throw new Error(`Ambiguous Codex delegation route "${routeInput}"`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (matches.length === 0) {
|
|
47
|
+
throw new Error(`Unknown Codex delegation route "${routeInput}"`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const [routeId, routeSpec] = matches[0];
|
|
51
|
+
return { routeId, routeSpec };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function resolveRouteRecord(routeInput, projectRoot = PROJECT_ROOT, matrix = loadDelegationMatrix(projectRoot)) {
|
|
55
|
+
if (
|
|
56
|
+
routeInput &&
|
|
57
|
+
typeof routeInput === 'object' &&
|
|
58
|
+
typeof routeInput.routeId === 'string' &&
|
|
59
|
+
routeInput.routeSpec &&
|
|
60
|
+
typeof routeInput.routeSpec === 'object'
|
|
61
|
+
) {
|
|
62
|
+
return routeInput;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return resolveDelegationRoute(routeInput, projectRoot, matrix);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function routeMentionsSource(routeSpec, sourceInput) {
|
|
69
|
+
const normalizedSource = normalizeActorInput(sourceInput);
|
|
70
|
+
if (!normalizedSource) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (normalizeActorInput(routeSpec.owner) === normalizedSource) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (routeSpec.delegationChain || []).some(
|
|
79
|
+
(step) =>
|
|
80
|
+
normalizeActorInput(step.from) === normalizedSource ||
|
|
81
|
+
normalizeActorInput(step.to) === normalizedSource,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function buildHandoffPacket(routeInput, projectRoot = PROJECT_ROOT, matrix = loadDelegationMatrix(projectRoot)) {
|
|
86
|
+
const { routeId, routeSpec } = resolveRouteRecord(routeInput, projectRoot, matrix);
|
|
87
|
+
const nextStep = routeSpec.delegationChain?.[0] || null;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
routeId,
|
|
91
|
+
mission: routeSpec.mission,
|
|
92
|
+
phase: matrix.phase || 'W5 / Delegation Matrix Parity',
|
|
93
|
+
owner: routeSpec.owner,
|
|
94
|
+
classification: routeSpec.classification,
|
|
95
|
+
summary: routeSpec.summary || '',
|
|
96
|
+
inputs: routeSpec.inputs || [],
|
|
97
|
+
outputs: routeSpec.outputs || [],
|
|
98
|
+
validators: routeSpec.validators || [],
|
|
99
|
+
sharedSurfaceRisk: routeSpec.sharedSurfaceRisk || 'low',
|
|
100
|
+
nextHandoff: {
|
|
101
|
+
to: nextStep?.to || routeSpec.owner,
|
|
102
|
+
artifact: routeSpec.outputs?.[0] || 'handoff-packet',
|
|
103
|
+
},
|
|
104
|
+
delegationChain: routeSpec.delegationChain || [],
|
|
105
|
+
resources: routeSpec.resources || [],
|
|
106
|
+
notes: routeSpec.notes || [],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function resolveCodexDelegation(routeInput, projectRoot = PROJECT_ROOT, options = {}) {
|
|
111
|
+
const matrix = options.matrix || loadDelegationMatrix(projectRoot);
|
|
112
|
+
const { routeId, routeSpec } = resolveDelegationRoute(routeInput, projectRoot, matrix);
|
|
113
|
+
|
|
114
|
+
if (options.source && !routeMentionsSource(routeSpec, options.source)) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
`Codex delegation route "${routeId}" is not available from source "${options.source}"`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
routeId,
|
|
122
|
+
owner: routeSpec.owner,
|
|
123
|
+
requestType: routeSpec.requestType,
|
|
124
|
+
classification: routeSpec.classification,
|
|
125
|
+
mission: routeSpec.mission,
|
|
126
|
+
summary: routeSpec.summary || '',
|
|
127
|
+
inputs: routeSpec.inputs || [],
|
|
128
|
+
outputs: routeSpec.outputs || [],
|
|
129
|
+
validators: routeSpec.validators || [],
|
|
130
|
+
sharedSurfaceRisk: routeSpec.sharedSurfaceRisk || 'low',
|
|
131
|
+
resources: routeSpec.resources || [],
|
|
132
|
+
delegationChain: routeSpec.delegationChain || [],
|
|
133
|
+
handoffPacket: buildHandoffPacket({ routeId, routeSpec }, projectRoot, matrix),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
138
|
+
const flags = new Set(argv.filter((arg) => arg.startsWith('--')));
|
|
139
|
+
const args = argv.filter((arg) => !arg.startsWith('--'));
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
source: args.length > 1 ? args[0] : null,
|
|
143
|
+
route: args.length > 1 ? args[1] : args[0],
|
|
144
|
+
json: flags.has('--json'),
|
|
145
|
+
packet: flags.has('--packet'),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function formatHumanResult(result) {
|
|
150
|
+
const nextHandoff = result.handoffPacket?.nextHandoff?.to || 'n/a';
|
|
151
|
+
const delegationPath = (result.delegationChain || [])
|
|
152
|
+
.map((step) => `${step.from} -> ${step.to}`)
|
|
153
|
+
.join(' | ');
|
|
154
|
+
|
|
155
|
+
return [
|
|
156
|
+
`Route: ${result.routeId}`,
|
|
157
|
+
`Owner: ${result.owner}`,
|
|
158
|
+
`Request Type: ${result.requestType}`,
|
|
159
|
+
`Classification: ${result.classification}`,
|
|
160
|
+
`Next Handoff: ${nextHandoff}`,
|
|
161
|
+
`Delegation Chain: ${delegationPath || 'n/a'}`,
|
|
162
|
+
].join('\n');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function main() {
|
|
166
|
+
const args = parseArgs();
|
|
167
|
+
if (!args.route) {
|
|
168
|
+
console.error(
|
|
169
|
+
'Usage: node .codex/scripts/resolve-codex-delegation-parity.js <route> [--json] [--packet]\n' +
|
|
170
|
+
' or: node .codex/scripts/resolve-codex-delegation-parity.js <source-agent> <route> [--json] [--packet]',
|
|
171
|
+
);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
const result = resolveCodexDelegation(args.route, PROJECT_ROOT, {
|
|
177
|
+
source: args.source,
|
|
178
|
+
});
|
|
179
|
+
const payload = args.packet ? result.handoffPacket : result;
|
|
180
|
+
|
|
181
|
+
if (args.json || args.packet) {
|
|
182
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
183
|
+
} else {
|
|
184
|
+
console.log(formatHumanResult(result));
|
|
185
|
+
}
|
|
186
|
+
} catch (error) {
|
|
187
|
+
console.error(error.message);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (require.main === module) {
|
|
193
|
+
main();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
module.exports = {
|
|
197
|
+
MATRIX_PATH,
|
|
198
|
+
loadDelegationMatrix,
|
|
199
|
+
normalizeRouteInput,
|
|
200
|
+
resolveDelegationRoute,
|
|
201
|
+
buildHandoffPacket,
|
|
202
|
+
resolveCodexDelegation,
|
|
203
|
+
parseArgs,
|
|
204
|
+
formatHumanResult,
|
|
205
|
+
};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
|
|
8
|
+
|
|
9
|
+
function loadDelegationMatrix(projectRoot = PROJECT_ROOT) {
|
|
10
|
+
const matrixPath = path.join(projectRoot, '.codex', 'delegation-matrix.json');
|
|
11
|
+
const raw = fs.readFileSync(matrixPath, 'utf8');
|
|
12
|
+
return JSON.parse(raw);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizeAgentInput(value) {
|
|
16
|
+
return String(value || '').trim().replace(/^@/, '').toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function normalizeRouteInput(value) {
|
|
20
|
+
return String(value || '').trim().replace(/^\*/, '').toLowerCase();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function collectAliases(routeId, routeSpec) {
|
|
24
|
+
return [routeId, ...(routeSpec.aliases || [])]
|
|
25
|
+
.map((alias) => normalizeRouteInput(alias))
|
|
26
|
+
.filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getSourceAgentConfig(matrix, agentInput) {
|
|
30
|
+
const normalized = normalizeAgentInput(agentInput);
|
|
31
|
+
|
|
32
|
+
if (['sinapse-orqx', 'imperator'].includes(normalized)) {
|
|
33
|
+
return {
|
|
34
|
+
sourceAgent: 'sinapse-orqx',
|
|
35
|
+
routes: {
|
|
36
|
+
...(matrix.masterRoutes || {}),
|
|
37
|
+
...(matrix.orqxRoutes || {}),
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const matches = Object.entries(matrix.specialistRoutes || {})
|
|
43
|
+
.filter(([sourceAgentId, sourceSpec]) => {
|
|
44
|
+
const aliases = [sourceAgentId, ...(sourceSpec.aliases || [])]
|
|
45
|
+
.map((alias) => normalizeAgentInput(alias))
|
|
46
|
+
.filter(Boolean);
|
|
47
|
+
return aliases.includes(normalized);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (matches.length > 1) {
|
|
51
|
+
throw new Error(`Ambiguous Codex delegation source "${agentInput}"`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (matches.length === 1) {
|
|
55
|
+
return {
|
|
56
|
+
sourceAgent: matches[0][0],
|
|
57
|
+
routes: matches[0][1].routes || {},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function resolveRoute(routes, routeInput) {
|
|
65
|
+
const normalized = normalizeRouteInput(routeInput);
|
|
66
|
+
const matches = Object.entries(routes || {})
|
|
67
|
+
.filter(([routeId, routeSpec]) => collectAliases(routeId, routeSpec).includes(normalized));
|
|
68
|
+
|
|
69
|
+
if (matches.length > 1) {
|
|
70
|
+
throw new Error(`Ambiguous Codex delegation route "${routeInput}"`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (matches.length === 0) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
routeId: matches[0][0],
|
|
79
|
+
routeSpec: matches[0][1],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function resolveCodexDelegation(agentInput, routeInput, projectRoot = PROJECT_ROOT) {
|
|
84
|
+
const matrix = loadDelegationMatrix(projectRoot);
|
|
85
|
+
const source = getSourceAgentConfig(matrix, agentInput);
|
|
86
|
+
if (!source) {
|
|
87
|
+
throw new Error(`Unknown Codex delegation source "${agentInput}"`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const route = resolveRoute(source.routes, routeInput);
|
|
91
|
+
if (!route) {
|
|
92
|
+
throw new Error(`Unknown Codex delegation route "${routeInput}" for source "${source.sourceAgent}"`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
sourceAgent: source.sourceAgent,
|
|
97
|
+
routeId: route.routeId,
|
|
98
|
+
classification: route.routeSpec.classification,
|
|
99
|
+
target: route.routeSpec.target,
|
|
100
|
+
handoff: route.routeSpec.handoff || null,
|
|
101
|
+
sourceDocs: route.routeSpec.sourceDocs || [],
|
|
102
|
+
handoffSchemaPath: matrix.handoffSchemaPath,
|
|
103
|
+
handoffTemplatePath: matrix.handoffTemplatePath,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
108
|
+
const args = argv.filter((arg) => !arg.startsWith('--'));
|
|
109
|
+
const flags = new Set(argv.filter((arg) => arg.startsWith('--')));
|
|
110
|
+
return {
|
|
111
|
+
agent: args[0],
|
|
112
|
+
route: args[1],
|
|
113
|
+
json: flags.has('--json'),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function formatHumanResult(result) {
|
|
118
|
+
const lines = [
|
|
119
|
+
`Source: ${result.sourceAgent}`,
|
|
120
|
+
`Route: ${result.routeId}`,
|
|
121
|
+
`Classification: ${result.classification}`,
|
|
122
|
+
`Target Type: ${result.target.type}`,
|
|
123
|
+
`Target Agent: ${result.target.agentId}`,
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
if (result.target.commandId) {
|
|
127
|
+
lines.push(`Target Command: ${result.target.commandId}`);
|
|
128
|
+
}
|
|
129
|
+
if (result.target.docPath) {
|
|
130
|
+
lines.push(`Target Doc: ${result.target.docPath}`);
|
|
131
|
+
}
|
|
132
|
+
if (result.target.taskPath) {
|
|
133
|
+
lines.push(`Target Task: ${result.target.taskPath}`);
|
|
134
|
+
}
|
|
135
|
+
if (result.handoff) {
|
|
136
|
+
lines.push(`Next Handoff: ${result.handoff.nextHandoff}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return lines.join('\n');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function main() {
|
|
143
|
+
const args = parseArgs();
|
|
144
|
+
if (!args.agent || !args.route) {
|
|
145
|
+
console.error('Usage: node .codex/scripts/resolve-codex-delegation.js <source-agent> <route> [--json]');
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
const result = resolveCodexDelegation(args.agent, args.route);
|
|
151
|
+
if (args.json) {
|
|
152
|
+
console.log(JSON.stringify(result, null, 2));
|
|
153
|
+
} else {
|
|
154
|
+
console.log(formatHumanResult(result));
|
|
155
|
+
}
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error(error.message);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (require.main === module) {
|
|
163
|
+
main();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = {
|
|
167
|
+
loadDelegationMatrix,
|
|
168
|
+
normalizeAgentInput,
|
|
169
|
+
normalizeRouteInput,
|
|
170
|
+
collectAliases,
|
|
171
|
+
getSourceAgentConfig,
|
|
172
|
+
resolveRoute,
|
|
173
|
+
resolveCodexDelegation,
|
|
174
|
+
parseArgs,
|
|
175
|
+
formatHumanResult,
|
|
176
|
+
};
|
|
@@ -11,19 +11,21 @@ Diagnose a request and choose the smallest correct Codex routing path.
|
|
|
11
11
|
## Steps
|
|
12
12
|
|
|
13
13
|
1. Read `.codex/catalog.json`.
|
|
14
|
-
2.
|
|
14
|
+
2. Read `.codex/delegation-parity.json`.
|
|
15
|
+
3. Classify the request as one of:
|
|
15
16
|
- simple + single-domain
|
|
16
17
|
- complex + single-domain
|
|
17
18
|
- complex + multi-domain
|
|
18
19
|
- framework/development workflow
|
|
19
|
-
|
|
20
|
+
4. Prefer the smallest correct path:
|
|
20
21
|
- simple + single-domain -> relevant `*-orqx` or validated framework agent
|
|
21
22
|
- complex + single-domain -> relevant `*-orqx`
|
|
22
23
|
- complex + multi-domain -> `sinapse-orqx` orchestration plan
|
|
23
24
|
- framework/development workflow -> `sinapse-pm`, `sinapse-po`, `sinapse-sm`, `sinapse-dev`, or `sinapse-qa`
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
5. When the request matches an approved handoff route, resolve it through `.codex/delegation-parity.json`.
|
|
26
|
+
6. If the request depends on a starred command, resolve it through `.codex/command-registry.json`.
|
|
27
|
+
7. Only recommend direct specialist routing from `.codex/agents` when the delegation matrix marks it as `exploratory`.
|
|
28
|
+
8. Return the recommended route with rationale, classification, and next action.
|
|
27
29
|
|
|
28
30
|
## Output Contract
|
|
29
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SINAPSE Constitution
|
|
2
2
|
|
|
3
|
-
> **Version:** 2.
|
|
3
|
+
> **Version:** 2.2.0 | **Ratified:** 2025-01-30 | **Last Amended:** 2026-04-03
|
|
4
4
|
|
|
5
5
|
Este documento define os princípios fundamentais e inegociáveis do SINAPSE. Todos os agentes, tasks, e workflows DEVEM respeitar estes princípios. Violações são bloqueadas automaticamente via gates.
|
|
6
6
|
|
|
@@ -239,6 +239,72 @@ Usuários são product builders, não especialistas em git. Agentes DEVEM gerenc
|
|
|
239
239
|
|
|
240
240
|
---
|
|
241
241
|
|
|
242
|
+
### X. Security & Data Protection (NON-NEGOTIABLE)
|
|
243
|
+
|
|
244
|
+
Todo projeto que manipula dados de usuarios DEVE seguir praticas de seguranca rigorosas. Nenhum atalho e aceito — seguranca e inegociavel desde o primeiro commit.
|
|
245
|
+
|
|
246
|
+
**Regras — Banco de Dados:**
|
|
247
|
+
- MUST: TODA tabela com dados de usuario DEVE ter Row Level Security (RLS) ativado
|
|
248
|
+
- MUST: Chave `service_role` NUNCA exposta no frontend — apenas no servidor
|
|
249
|
+
- MUST: Queries DEVEM ser parametrizadas (`$1, $2`) — NUNCA string interpolation
|
|
250
|
+
- MUST: Cada servico DEVE usar role com privilegios minimos (principio do menor privilegio)
|
|
251
|
+
- MUST: Dados sensiveis (CPF, cartao, saude) DEVEM ser criptografados em repouso
|
|
252
|
+
|
|
253
|
+
**Regras — APIs:**
|
|
254
|
+
- MUST: TODA API publica DEVE ter rate limiting configurado
|
|
255
|
+
- MUST: TODA API DEVE validar input (schema validation com Zod ou equivalente)
|
|
256
|
+
- MUST: CORS DEVE restringir origens permitidas (NUNCA `origin: '*'` em producao)
|
|
257
|
+
- MUST: Headers de seguranca DEVEM estar ativos (helmet ou equivalente)
|
|
258
|
+
- MUST: Autenticacao DEVE usar OAuth 2.0 / OIDC ou Supabase Auth
|
|
259
|
+
|
|
260
|
+
**Regras — Secrets & Keys:**
|
|
261
|
+
- MUST: API keys, tokens e credenciais DEVEM estar em variaveis de ambiente (.env)
|
|
262
|
+
- MUST: Arquivos .env NUNCA commitados no repositorio (gitignore obrigatorio)
|
|
263
|
+
- MUST: .env.example DEVE existir com placeholders (sem valores reais)
|
|
264
|
+
- MUST: Variaveis prefixadas com `NEXT_PUBLIC_` sao PUBLICAS — NUNCA colocar secrets nelas
|
|
265
|
+
- MUST: Rotacao de chaves DEVE ser feita ao menor sinal de vazamento
|
|
266
|
+
- MUST NOT: Nenhum agente pode commitar arquivos contendo credentials em plaintext
|
|
267
|
+
|
|
268
|
+
**Regras — LGPD (Lei Geral de Protecao de Dados):**
|
|
269
|
+
- MUST: Consentimento explicito DEVE ser coletado antes de processar dados pessoais (Art. 7)
|
|
270
|
+
- MUST: Usuarios DEVEM poder acessar, corrigir e deletar seus dados (Art. 18)
|
|
271
|
+
- MUST: DPO/Encarregado DEVE ser designado para projetos com dados pessoais (Art. 37)
|
|
272
|
+
- MUST: Medidas de seguranca tecnica DEVEM proteger dados contra acesso nao autorizado (Art. 46)
|
|
273
|
+
- MUST: Incidentes de seguranca DEVEM ser notificados a ANPD e titulares (Art. 48)
|
|
274
|
+
- MUST: Dados pessoais DEVEM ter periodo de retencao definido e documentado
|
|
275
|
+
- MUST: Audit logging DEVE registrar todo acesso a dados pessoais
|
|
276
|
+
|
|
277
|
+
**Regras — Repositorio:**
|
|
278
|
+
- MUST: Repositorios com codigo de producao DEVEM ser privados por padrao
|
|
279
|
+
- MUST: Branch protection DEVE estar ativa em main (PR + approval)
|
|
280
|
+
- MUST: GitHub Secret Scanning DEVE estar habilitado
|
|
281
|
+
- MUST: Dependabot DEVE estar configurado para alertas de seguranca
|
|
282
|
+
- MUST: CODEOWNERS DEVE proteger arquivos criticos
|
|
283
|
+
|
|
284
|
+
**Delegacao:**
|
|
285
|
+
|
|
286
|
+
| Dominio de Seguranca | Agente Responsavel |
|
|
287
|
+
|----------------------|-------------------|
|
|
288
|
+
| Threat modeling, MITRE ATT&CK | @cyber-orqx → Shield (threat-analyst) |
|
|
289
|
+
| Penetration testing, OWASP | @cyber-orqx → Breach (penetration-tester) |
|
|
290
|
+
| SOC, detection engineering | @cyber-orqx → Sentinel (soc-analyst) |
|
|
291
|
+
| Incident response | @cyber-orqx → Rapid (incident-responder) |
|
|
292
|
+
| Cloud security, IAM, encryption | @cyber-orqx → Nimbus (cloud-security-engineer) |
|
|
293
|
+
| Network security, zero trust | @cyber-orqx → Wire (network-security-engineer) |
|
|
294
|
+
| LGPD, GDPR, SOC 2, ISO 27001 | @cyber-orqx → Govern (compliance-officer) |
|
|
295
|
+
| Database security, RLS | @data-engineer (Dara) |
|
|
296
|
+
| Application security, hooks | @developer (Dex) + hooks automaticos |
|
|
297
|
+
|
|
298
|
+
**Gates:**
|
|
299
|
+
- Hook `sql-governance.py` — BLOCK DDL perigoso
|
|
300
|
+
- Hook `secret-scanning.cjs` — BLOCK credentials em commits
|
|
301
|
+
- Hook `staged-secret-scan.js` — BLOCK .env e tokens pre-commit
|
|
302
|
+
- Checklist: `.claude/rules/security-data-protection.md`
|
|
303
|
+
|
|
304
|
+
**Rule file:** `.claude/rules/security-data-protection.md`
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
242
308
|
## Governance
|
|
243
309
|
|
|
244
310
|
### Amendment Process
|
|
@@ -28,6 +28,7 @@ const EXPECTED_ARTICLES = [
|
|
|
28
28
|
{ number: 'VII', title: 'Ecosystem Metrics Accuracy', severity: 'NON-NEGOTIABLE' },
|
|
29
29
|
{ number: 'VIII', title: 'Mandatory Delegation', severity: 'NON-NEGOTIABLE' },
|
|
30
30
|
{ number: 'IX', title: 'Safe Collaboration', severity: 'NON-NEGOTIABLE' },
|
|
31
|
+
{ number: 'X', title: 'Security & Data Protection', severity: 'NON-NEGOTIABLE' },
|
|
31
32
|
];
|
|
32
33
|
|
|
33
34
|
/**
|