@formigio/fazemos-cli 0.10.67 → 0.10.75
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/dist/approvals.d.ts +1 -1
- package/dist/approvals.js +50 -19
- package/dist/approvals.js.map +1 -1
- package/dist/commands/preflight.d.ts +41 -0
- package/dist/commands/preflight.js +706 -0
- package/dist/commands/preflight.js.map +1 -0
- package/dist/commands/provision.d.ts +29 -0
- package/dist/commands/provision.js +382 -0
- package/dist/commands/provision.js.map +1 -0
- package/dist/index.js +124 -5
- package/dist/index.js.map +1 -1
- package/dist/pause.js +42 -11
- package/dist/pause.js.map +1 -1
- package/dist/preflight/repoRead.d.ts +65 -0
- package/dist/preflight/repoRead.js +194 -0
- package/dist/preflight/repoRead.js.map +1 -0
- package/dist/preflight/roster.d.ts +65 -0
- package/dist/preflight/roster.js +153 -0
- package/dist/preflight/roster.js.map +1 -0
- package/dist/preflight/row1_member.d.ts +8 -0
- package/dist/preflight/row1_member.js +64 -0
- package/dist/preflight/row1_member.js.map +1 -0
- package/dist/preflight/row2_roleRegistration.d.ts +18 -0
- package/dist/preflight/row2_roleRegistration.js +156 -0
- package/dist/preflight/row2_roleRegistration.js.map +1 -0
- package/dist/preflight/row3_persona.d.ts +24 -0
- package/dist/preflight/row3_persona.js +92 -0
- package/dist/preflight/row3_persona.js.map +1 -0
- package/dist/preflight/row3_playbook.d.ts +30 -0
- package/dist/preflight/row3_playbook.js +142 -0
- package/dist/preflight/row3_playbook.js.map +1 -0
- package/dist/preflight/row3_rolesJson.d.ts +12 -0
- package/dist/preflight/row3_rolesJson.js +38 -0
- package/dist/preflight/row3_rolesJson.js.map +1 -0
- package/dist/preflight/row3_workspace.d.ts +24 -0
- package/dist/preflight/row3_workspace.js +253 -0
- package/dist/preflight/row3_workspace.js.map +1 -0
- package/dist/preflight/row4_ssm.d.ts +57 -0
- package/dist/preflight/row4_ssm.js +235 -0
- package/dist/preflight/row4_ssm.js.map +1 -0
- package/dist/preflight/row5_workerLambdaWakeConfig.d.ts +20 -0
- package/dist/preflight/row5_workerLambdaWakeConfig.js +113 -0
- package/dist/preflight/row5_workerLambdaWakeConfig.js.map +1 -0
- package/dist/preflight/row6_ingest.d.ts +20 -0
- package/dist/preflight/row6_ingest.js +178 -0
- package/dist/preflight/row6_ingest.js.map +1 -0
- package/dist/preflight/schema.d.ts +175 -0
- package/dist/preflight/schema.js +62 -0
- package/dist/preflight/schema.js.map +1 -0
- package/dist/preflight/workerLambdas.d.ts +22 -0
- package/dist/preflight/workerLambdas.js +25 -0
- package/dist/preflight/workerLambdas.js.map +1 -0
- package/package.json +1 -1
package/dist/pause.js
CHANGED
|
@@ -33,17 +33,26 @@ import { api } from './api.js';
|
|
|
33
33
|
* (both) → error: mutually exclusive
|
|
34
34
|
*/
|
|
35
35
|
function resolveScope(opts) {
|
|
36
|
-
|
|
36
|
+
// Test for PRESENCE, not truthiness. `--role ""` (the standard agent idiom
|
|
37
|
+
// `--role "$ROLE"` with an unset shell variable) yields '', which is falsy —
|
|
38
|
+
// so the old `if (opts.role)` skipped the branch entirely, the empty-string
|
|
39
|
+
// guard below was unreachable, and control fell through to `scope: 'global'`.
|
|
40
|
+
// A typo'd variable silently escalated a per-role pause into an ORG-WIDE one.
|
|
41
|
+
const hasRole = opts.role !== undefined;
|
|
42
|
+
const hasStream = opts.stream !== undefined;
|
|
43
|
+
if (hasRole && hasStream) {
|
|
37
44
|
throw new Error('--role and --stream are mutually exclusive; specify at most one.');
|
|
38
45
|
}
|
|
39
|
-
if (
|
|
40
|
-
if (!opts.role.trim())
|
|
41
|
-
throw new Error('--role
|
|
46
|
+
if (hasRole) {
|
|
47
|
+
if (!opts.role.trim()) {
|
|
48
|
+
throw new Error('--role was given an empty value. Omit --role for a global pause.');
|
|
49
|
+
}
|
|
42
50
|
return { scope: 'role', scope_key: opts.role.trim().toLowerCase() };
|
|
43
51
|
}
|
|
44
|
-
if (
|
|
45
|
-
if (!opts.stream.trim())
|
|
46
|
-
throw new Error('--stream
|
|
52
|
+
if (hasStream) {
|
|
53
|
+
if (!opts.stream.trim()) {
|
|
54
|
+
throw new Error('--stream was given an empty value. Omit --stream for a global pause.');
|
|
55
|
+
}
|
|
47
56
|
return { scope: 'stream', scope_key: opts.stream.trim() };
|
|
48
57
|
}
|
|
49
58
|
return { scope: 'global' };
|
|
@@ -83,12 +92,26 @@ export function registerPauseCommands(program) {
|
|
|
83
92
|
'Requires admin or owner role. --reason is mandatory (audit trail).')
|
|
84
93
|
.option('--role <slug>', 'pause a specific agent role (lower-cased role-slug)')
|
|
85
94
|
.option('--stream <pipeline-instance-id>', 'pause a specific pipeline instance stream')
|
|
86
|
-
|
|
95
|
+
// NOT requiredOption: commander checks ancestors for missing mandatory
|
|
96
|
+
// options, so a required --reason here fires on `fazemos pause status`
|
|
97
|
+
// too — the documented read path errored out demanding a value it then
|
|
98
|
+
// discarded. Enforced in the action instead.
|
|
99
|
+
.option('--reason <text>', 'reason for the pause (required for audit trail)')
|
|
87
100
|
.option('--json', 'output machine-readable JSON')
|
|
101
|
+
// SECURITY: `pause` carries BOTH this action and a `status` subcommand.
|
|
102
|
+
// Commander dispatches to a subcommand only when operands[0] matches one;
|
|
103
|
+
// otherwise it runs the PARENT action and drops the stray operand. So
|
|
104
|
+
// `fazemos pause resume --reason x`, `pause off`, or any typo silently
|
|
105
|
+
// SET AN ORG-WIDE PAUSE blocking every agent launch, and exited 0.
|
|
106
|
+
// Refusing excess operands turns those into a usage error.
|
|
107
|
+
.allowExcessArguments(false)
|
|
88
108
|
.action(async (opts) => {
|
|
89
109
|
try {
|
|
110
|
+
if (!opts.reason || !opts.reason.trim()) {
|
|
111
|
+
throw new Error("--reason is required when setting a pause (audit trail). To read current pauses use 'fazemos pause status'.");
|
|
112
|
+
}
|
|
90
113
|
const { scope, scope_key } = resolveScope(opts);
|
|
91
|
-
const body = { scope, reason: opts.reason };
|
|
114
|
+
const body = { scope, reason: opts.reason.trim() };
|
|
92
115
|
if (scope_key !== undefined)
|
|
93
116
|
body.scope_key = scope_key;
|
|
94
117
|
const data = await api('POST', '/api/control-plane/pause', body, {
|
|
@@ -172,12 +195,20 @@ export function registerPauseCommands(program) {
|
|
|
172
195
|
'Requires admin or owner role. --reason is mandatory (audit trail).')
|
|
173
196
|
.option('--role <slug>', 'clear the pause for a specific agent role')
|
|
174
197
|
.option('--stream <pipeline-instance-id>', 'clear the pause for a specific pipeline instance')
|
|
175
|
-
.
|
|
198
|
+
.option('--reason <text>', 'reason for the resume (maps to clear_reason; required for audit)')
|
|
176
199
|
.option('--json', 'output machine-readable JSON')
|
|
200
|
+
// Mirrors the pause guard: `fazemos resume status --reason x` used to CLEAR
|
|
201
|
+
// a pause rather than read one. resume hosts no subcommands today, but the
|
|
202
|
+
// stray-operand refusal is what makes a typo a usage error instead of a
|
|
203
|
+
// fleet-wide control-plane write.
|
|
204
|
+
.allowExcessArguments(false)
|
|
177
205
|
.action(async (opts) => {
|
|
178
206
|
try {
|
|
207
|
+
if (!opts.reason || !opts.reason.trim()) {
|
|
208
|
+
throw new Error('--reason is required when clearing a pause (audit trail).');
|
|
209
|
+
}
|
|
179
210
|
const { scope, scope_key } = resolveScope(opts);
|
|
180
|
-
const body = { scope, clear_reason: opts.reason };
|
|
211
|
+
const body = { scope, clear_reason: opts.reason.trim() };
|
|
181
212
|
if (scope_key !== undefined)
|
|
182
213
|
body.scope_key = scope_key;
|
|
183
214
|
const data = await api('DELETE', '/api/control-plane/pause', body, {
|
package/dist/pause.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pause.js","sourceRoot":"","sources":["../src/pause.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,gFAAgF;AAChF,qEAAqE;AACrE,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAkB/B;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,IAAwC;IAI5D,
|
|
1
|
+
{"version":3,"file":"pause.js","sourceRoot":"","sources":["../src/pause.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 D3 — Remote workspace repo file reads via the operator's `gh` CLI.
|
|
3
|
+
*
|
|
4
|
+
* Row 3 checks (persona, playbook, roles.json entry) are verified against
|
|
5
|
+
* `origin/main` of the workspace repo — not the local working copy — so
|
|
6
|
+
* an uncommitted state doesn't produce false PASSes or FAILes.
|
|
7
|
+
*/
|
|
8
|
+
export interface RepoRef {
|
|
9
|
+
owner: string;
|
|
10
|
+
repo: string;
|
|
11
|
+
ref: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse a git remote URL into { owner, repo }.
|
|
15
|
+
* Handles HTTPS (https://github.com/owner/repo.git) and SSH (git@github.com:owner/repo.git).
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseGitHubUrl(url: string): {
|
|
18
|
+
owner: string;
|
|
19
|
+
repo: string;
|
|
20
|
+
} | null;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the GitHub owner/repo for a workspace by reading its git remote origin URL.
|
|
23
|
+
* Returns null if the workspace is not a GitHub repo or git is not available.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getWorkspaceGitHubRepo(workspaceRoot: string): RepoRef | null;
|
|
26
|
+
/**
|
|
27
|
+
* Check if `gh` CLI is installed and authenticated.
|
|
28
|
+
* Throws ToolingError if not.
|
|
29
|
+
*/
|
|
30
|
+
export declare function checkGhAvailable(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a file exists in the GitHub repo at origin/main.
|
|
33
|
+
* Calls `gh api` to query the Contents API.
|
|
34
|
+
* Returns true if file exists, false if 404.
|
|
35
|
+
* Throws ToolingError if gh fails for any other reason.
|
|
36
|
+
*/
|
|
37
|
+
export declare function checkFileExistsOnGitHub(repoRef: RepoRef, filePath: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Get file size in bytes from the GitHub repo at origin/main.
|
|
40
|
+
* Returns null if the file is not found (404).
|
|
41
|
+
* Returns 0 if the file exists but is empty.
|
|
42
|
+
* Throws ToolingError if gh fails for any other reason.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getFileSizeOnGitHub(repoRef: RepoRef, filePath: string): number | null;
|
|
45
|
+
/**
|
|
46
|
+
* List filenames in a directory on GitHub at origin/main.
|
|
47
|
+
* Returns null if the path is not found (404) or if the path is a file (not a dir).
|
|
48
|
+
* Returns an array of filenames if the path is a directory.
|
|
49
|
+
* Throws ToolingError if gh fails for any other reason.
|
|
50
|
+
*/
|
|
51
|
+
export declare function listDirectoryFilenamesOnGitHub(repoRef: RepoRef, dirPath: string): string[] | null;
|
|
52
|
+
/**
|
|
53
|
+
* Get the full decoded text content of a file from the GitHub repo at origin/main.
|
|
54
|
+
* Returns null if the file is not found (404).
|
|
55
|
+
* Throws ToolingError if gh fails for any other reason.
|
|
56
|
+
*
|
|
57
|
+
* The GitHub Contents API returns base64-encoded content (≤1 MB). We decode it
|
|
58
|
+
* in Node.js after receiving the raw base64 string from gh. This is a content
|
|
59
|
+
* fetch (not just metadata), which is appropriate for the row-3a body check —
|
|
60
|
+
* persona files are small markdown docs and the extra payload is negligible.
|
|
61
|
+
*/
|
|
62
|
+
export declare function getFileContentOnGitHub(repoRef: RepoRef, filePath: string): string | null;
|
|
63
|
+
export declare class ToolingError extends Error {
|
|
64
|
+
constructor(message: string);
|
|
65
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 D3 — Remote workspace repo file reads via the operator's `gh` CLI.
|
|
3
|
+
*
|
|
4
|
+
* Row 3 checks (persona, playbook, roles.json entry) are verified against
|
|
5
|
+
* `origin/main` of the workspace repo — not the local working copy — so
|
|
6
|
+
* an uncommitted state doesn't produce false PASSes or FAILes.
|
|
7
|
+
*/
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
/**
|
|
10
|
+
* Parse a git remote URL into { owner, repo }.
|
|
11
|
+
* Handles HTTPS (https://github.com/owner/repo.git) and SSH (git@github.com:owner/repo.git).
|
|
12
|
+
*/
|
|
13
|
+
export function parseGitHubUrl(url) {
|
|
14
|
+
// HTTPS
|
|
15
|
+
const httpsMatch = url.match(/github\.com\/([^/]+)\/([^/.]+?)(?:\.git)?\s*$/);
|
|
16
|
+
if (httpsMatch)
|
|
17
|
+
return { owner: httpsMatch[1], repo: httpsMatch[2] };
|
|
18
|
+
// SSH
|
|
19
|
+
const sshMatch = url.match(/github\.com:([^/]+)\/([^/.]+?)(?:\.git)?\s*$/);
|
|
20
|
+
if (sshMatch)
|
|
21
|
+
return { owner: sshMatch[1], repo: sshMatch[2] };
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the GitHub owner/repo for a workspace by reading its git remote origin URL.
|
|
26
|
+
* Returns null if the workspace is not a GitHub repo or git is not available.
|
|
27
|
+
*/
|
|
28
|
+
export function getWorkspaceGitHubRepo(workspaceRoot) {
|
|
29
|
+
try {
|
|
30
|
+
const url = execSync('git config --get remote.origin.url', {
|
|
31
|
+
cwd: workspaceRoot,
|
|
32
|
+
encoding: 'utf-8',
|
|
33
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
34
|
+
}).trim();
|
|
35
|
+
const parsed = parseGitHubUrl(url);
|
|
36
|
+
if (!parsed)
|
|
37
|
+
return null;
|
|
38
|
+
return { ...parsed, ref: 'main' };
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if `gh` CLI is installed and authenticated.
|
|
46
|
+
* Throws ToolingError if not.
|
|
47
|
+
*/
|
|
48
|
+
export function checkGhAvailable() {
|
|
49
|
+
try {
|
|
50
|
+
execSync('gh auth status', {
|
|
51
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
52
|
+
encoding: 'utf-8',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
const msg = String(err.stderr ?? err.stdout ?? err.message ?? '');
|
|
57
|
+
if (msg.includes('not logged into any') || msg.includes('not logged in') || msg.includes('You are not logged')) {
|
|
58
|
+
throw new ToolingError('gh CLI is not authenticated. Run: gh auth login');
|
|
59
|
+
}
|
|
60
|
+
throw new ToolingError('gh CLI is not installed or not in PATH. Install with: brew install gh && gh auth login');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if a file exists in the GitHub repo at origin/main.
|
|
65
|
+
* Calls `gh api` to query the Contents API.
|
|
66
|
+
* Returns true if file exists, false if 404.
|
|
67
|
+
* Throws ToolingError if gh fails for any other reason.
|
|
68
|
+
*/
|
|
69
|
+
export function checkFileExistsOnGitHub(repoRef, filePath) {
|
|
70
|
+
// Encode the path for the URL, but keep slashes
|
|
71
|
+
const encodedPath = filePath.split('/').map(encodeURIComponent).join('/');
|
|
72
|
+
const url = `repos/${repoRef.owner}/${repoRef.repo}/contents/${encodedPath}?ref=${repoRef.ref}`;
|
|
73
|
+
try {
|
|
74
|
+
execSync(`gh api "${url}" --jq '.type'`, {
|
|
75
|
+
encoding: 'utf-8',
|
|
76
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
77
|
+
});
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const stderr = String(err.stderr ?? '');
|
|
82
|
+
const stdout = String(err.stdout ?? '');
|
|
83
|
+
if (stderr.includes('Not Found') ||
|
|
84
|
+
stderr.includes('404') ||
|
|
85
|
+
stdout.includes('Not Found') ||
|
|
86
|
+
stdout.includes('"Not Found"')) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
// Other error — gh broken or auth issue
|
|
90
|
+
const detail = (stderr || stdout || String(err.message ?? '')).trim();
|
|
91
|
+
throw new ToolingError(`gh api call failed for ${filePath}: ${detail}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get file size in bytes from the GitHub repo at origin/main.
|
|
96
|
+
* Returns null if the file is not found (404).
|
|
97
|
+
* Returns 0 if the file exists but is empty.
|
|
98
|
+
* Throws ToolingError if gh fails for any other reason.
|
|
99
|
+
*/
|
|
100
|
+
export function getFileSizeOnGitHub(repoRef, filePath) {
|
|
101
|
+
const encodedPath = filePath.split('/').map(encodeURIComponent).join('/');
|
|
102
|
+
const url = `repos/${repoRef.owner}/${repoRef.repo}/contents/${encodedPath}?ref=${repoRef.ref}`;
|
|
103
|
+
try {
|
|
104
|
+
const result = execSync(`gh api "${url}" --jq '.size'`, {
|
|
105
|
+
encoding: 'utf-8',
|
|
106
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
107
|
+
}).trim();
|
|
108
|
+
const size = parseInt(result, 10);
|
|
109
|
+
return isNaN(size) ? 0 : size;
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
const stderr = String(err.stderr ?? '');
|
|
113
|
+
const stdout = String(err.stdout ?? '');
|
|
114
|
+
if (stderr.includes('Not Found') ||
|
|
115
|
+
stderr.includes('404') ||
|
|
116
|
+
stdout.includes('Not Found') ||
|
|
117
|
+
stdout.includes('"Not Found"')) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const detail = (stderr || stdout || String(err.message ?? '')).trim();
|
|
121
|
+
throw new ToolingError(`gh api call failed for ${filePath}: ${detail}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* List filenames in a directory on GitHub at origin/main.
|
|
126
|
+
* Returns null if the path is not found (404) or if the path is a file (not a dir).
|
|
127
|
+
* Returns an array of filenames if the path is a directory.
|
|
128
|
+
* Throws ToolingError if gh fails for any other reason.
|
|
129
|
+
*/
|
|
130
|
+
export function listDirectoryFilenamesOnGitHub(repoRef, dirPath) {
|
|
131
|
+
const encodedPath = dirPath.split('/').map(encodeURIComponent).join('/');
|
|
132
|
+
const url = `repos/${repoRef.owner}/${repoRef.repo}/contents/${encodedPath}?ref=${repoRef.ref}`;
|
|
133
|
+
try {
|
|
134
|
+
// The API returns an array for directories, an object for files.
|
|
135
|
+
// Use conditional jq to safely handle both: return null if not an array.
|
|
136
|
+
const result = execSync(`gh api "${url}" --jq 'if type == "array" then [.[].name] else null end'`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
137
|
+
if (result === 'null')
|
|
138
|
+
return null;
|
|
139
|
+
return JSON.parse(result);
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
const stderr = String(err.stderr ?? '');
|
|
143
|
+
const stdout = String(err.stdout ?? '');
|
|
144
|
+
if (stderr.includes('Not Found') ||
|
|
145
|
+
stderr.includes('404') ||
|
|
146
|
+
stdout.includes('Not Found') ||
|
|
147
|
+
stdout.includes('"Not Found"')) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
const detail = (stderr || stdout || String(err.message ?? '')).trim();
|
|
151
|
+
throw new ToolingError(`gh api directory listing failed for ${dirPath}: ${detail}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get the full decoded text content of a file from the GitHub repo at origin/main.
|
|
156
|
+
* Returns null if the file is not found (404).
|
|
157
|
+
* Throws ToolingError if gh fails for any other reason.
|
|
158
|
+
*
|
|
159
|
+
* The GitHub Contents API returns base64-encoded content (≤1 MB). We decode it
|
|
160
|
+
* in Node.js after receiving the raw base64 string from gh. This is a content
|
|
161
|
+
* fetch (not just metadata), which is appropriate for the row-3a body check —
|
|
162
|
+
* persona files are small markdown docs and the extra payload is negligible.
|
|
163
|
+
*/
|
|
164
|
+
export function getFileContentOnGitHub(repoRef, filePath) {
|
|
165
|
+
const encodedPath = filePath.split('/').map(encodeURIComponent).join('/');
|
|
166
|
+
const url = `repos/${repoRef.owner}/${repoRef.repo}/contents/${encodedPath}?ref=${repoRef.ref}`;
|
|
167
|
+
try {
|
|
168
|
+
// GitHub encodes file content as base64 with embedded newlines every 60 chars.
|
|
169
|
+
const rawB64 = execSync(`gh api "${url}" --jq '.content'`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
170
|
+
if (!rawB64 || rawB64 === 'null')
|
|
171
|
+
return null;
|
|
172
|
+
// Strip embedded newlines before decoding
|
|
173
|
+
return Buffer.from(rawB64.replace(/\n/g, ''), 'base64').toString('utf-8');
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
const stderr = String(err.stderr ?? '');
|
|
177
|
+
const stdout = String(err.stdout ?? '');
|
|
178
|
+
if (stderr.includes('Not Found') ||
|
|
179
|
+
stderr.includes('404') ||
|
|
180
|
+
stdout.includes('Not Found') ||
|
|
181
|
+
stdout.includes('"Not Found"')) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
const detail = (stderr || stdout || String(err.message ?? '')).trim();
|
|
185
|
+
throw new ToolingError(`gh api call failed for ${filePath}: ${detail}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
export class ToolingError extends Error {
|
|
189
|
+
constructor(message) {
|
|
190
|
+
super(message);
|
|
191
|
+
this.name = 'ToolingError';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=repoRead.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repoRead.js","sourceRoot":"","sources":["../../src/preflight/repoRead.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 r3 D9 — Roster loader.
|
|
3
|
+
*
|
|
4
|
+
* Classifies every project×role pair as one of:
|
|
5
|
+
* - `declared_here`: workspace's roles.json (root or per-project) declares the role
|
|
6
|
+
* with a filler and a project field.
|
|
7
|
+
* - `declared_cross_workspace`: root roles.json `cross_workspace_roles` block declares
|
|
8
|
+
* the role by pointer (workspace_path + registry_path); no filler, no project.
|
|
9
|
+
* - (absence = `not_declared`): neither of the above.
|
|
10
|
+
*
|
|
11
|
+
* `declared_here` and `declared_cross_workspace` are two distinct positive states.
|
|
12
|
+
* `not_declared` is absence — not a positive entry.
|
|
13
|
+
*/
|
|
14
|
+
import type { RolesRegistry, RoleEntry } from '../dispatch.js';
|
|
15
|
+
export interface DeclaredHereEntry {
|
|
16
|
+
classification: 'declared_here';
|
|
17
|
+
project_slug: string;
|
|
18
|
+
role_slug: string;
|
|
19
|
+
filler: RoleEntry['filler'];
|
|
20
|
+
source_file: string;
|
|
21
|
+
}
|
|
22
|
+
export interface DeclaredCrossWorkspaceEntry {
|
|
23
|
+
classification: 'declared_cross_workspace';
|
|
24
|
+
role_slug: string;
|
|
25
|
+
workspace_path: string;
|
|
26
|
+
registry_path: string;
|
|
27
|
+
source_file: string;
|
|
28
|
+
}
|
|
29
|
+
export interface Roster {
|
|
30
|
+
declared_here: DeclaredHereEntry[];
|
|
31
|
+
declared_cross_workspace: DeclaredCrossWorkspaceEntry[];
|
|
32
|
+
source_files: string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build the roster from a root registry (and any per-project registries under
|
|
36
|
+
* `<workspaceRoot>/projects/`).
|
|
37
|
+
*
|
|
38
|
+
* @param workspaceRoot - the workspace repo root (where .fazemos/roles.json lives)
|
|
39
|
+
* @param rootRegistry - the already-loaded root registry
|
|
40
|
+
*/
|
|
41
|
+
export declare function loadRoster(workspaceRoot: string, rootRegistry: RolesRegistry): Roster;
|
|
42
|
+
/**
|
|
43
|
+
* Return the roster classification for a (project_slug, role_slug) pair.
|
|
44
|
+
* `declared_here` wins over `declared_cross_workspace`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function classifyRoleForProject(roster: Roster, project_slug: string, role_slug: string): 'declared_here' | 'declared_cross_workspace' | 'not_declared';
|
|
47
|
+
/**
|
|
48
|
+
* Return all declared-here entries for a given role_slug, plus whether it is
|
|
49
|
+
* cross-workspace-declared.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getProjectsForRole(roster: Roster, role_slug: string): {
|
|
52
|
+
declared_here: DeclaredHereEntry[];
|
|
53
|
+
declared_cross_workspace: DeclaredCrossWorkspaceEntry | null;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Return all declared-here roles for a given project_slug, plus the cross-workspace
|
|
57
|
+
* entries (which are project-agnostic — they apply to the whole workspace).
|
|
58
|
+
*/
|
|
59
|
+
export declare function getRolesForProject(roster: Roster, project_slug: string): {
|
|
60
|
+
declared_here: DeclaredHereEntry[];
|
|
61
|
+
declared_cross_workspace: DeclaredCrossWorkspaceEntry[];
|
|
62
|
+
};
|
|
63
|
+
export declare class RosterLoadError extends Error {
|
|
64
|
+
constructor(message: string);
|
|
65
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 r3 D9 — Roster loader.
|
|
3
|
+
*
|
|
4
|
+
* Classifies every project×role pair as one of:
|
|
5
|
+
* - `declared_here`: workspace's roles.json (root or per-project) declares the role
|
|
6
|
+
* with a filler and a project field.
|
|
7
|
+
* - `declared_cross_workspace`: root roles.json `cross_workspace_roles` block declares
|
|
8
|
+
* the role by pointer (workspace_path + registry_path); no filler, no project.
|
|
9
|
+
* - (absence = `not_declared`): neither of the above.
|
|
10
|
+
*
|
|
11
|
+
* `declared_here` and `declared_cross_workspace` are two distinct positive states.
|
|
12
|
+
* `not_declared` is absence — not a positive entry.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
// ── Loader ─────────────────────────────────────────────────────────────────────
|
|
17
|
+
/**
|
|
18
|
+
* Build the roster from a root registry (and any per-project registries under
|
|
19
|
+
* `<workspaceRoot>/projects/`).
|
|
20
|
+
*
|
|
21
|
+
* @param workspaceRoot - the workspace repo root (where .fazemos/roles.json lives)
|
|
22
|
+
* @param rootRegistry - the already-loaded root registry
|
|
23
|
+
*/
|
|
24
|
+
export function loadRoster(workspaceRoot, rootRegistry) {
|
|
25
|
+
const declared_here = [];
|
|
26
|
+
const declared_cross_workspace = [];
|
|
27
|
+
const source_files = [];
|
|
28
|
+
function processRegistry(registry) {
|
|
29
|
+
if (!source_files.includes(registry._registryPath)) {
|
|
30
|
+
source_files.push(registry._registryPath);
|
|
31
|
+
}
|
|
32
|
+
const project_slug = registry.project ?? '';
|
|
33
|
+
// Locally-declared roles
|
|
34
|
+
for (const [role_slug, role] of Object.entries(registry.roles)) {
|
|
35
|
+
if (role.filler && project_slug) {
|
|
36
|
+
const exists = declared_here.some((e) => e.project_slug === project_slug && e.role_slug === role_slug);
|
|
37
|
+
if (!exists) {
|
|
38
|
+
declared_here.push({
|
|
39
|
+
classification: 'declared_here',
|
|
40
|
+
project_slug,
|
|
41
|
+
role_slug,
|
|
42
|
+
filler: role.filler,
|
|
43
|
+
source_file: registry._registryPath,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Cross-workspace pointers (only processed on root registry, where they live)
|
|
49
|
+
if (registry.cross_workspace_roles) {
|
|
50
|
+
for (const [role_slug, xref] of Object.entries(registry.cross_workspace_roles)) {
|
|
51
|
+
// Validate shape
|
|
52
|
+
if (!xref.workspace_path || !xref.registry_path) {
|
|
53
|
+
throw new RosterLoadError(`Malformed cross_workspace_roles entry for '${role_slug}' in ${registry._registryPath}: ` +
|
|
54
|
+
`must have workspace_path and registry_path.`);
|
|
55
|
+
}
|
|
56
|
+
const exists = declared_cross_workspace.some((e) => e.role_slug === role_slug);
|
|
57
|
+
if (!exists) {
|
|
58
|
+
declared_cross_workspace.push({
|
|
59
|
+
classification: 'declared_cross_workspace',
|
|
60
|
+
role_slug,
|
|
61
|
+
workspace_path: xref.workspace_path,
|
|
62
|
+
registry_path: xref.registry_path,
|
|
63
|
+
source_file: registry._registryPath,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Process root registry
|
|
70
|
+
processRegistry(rootRegistry);
|
|
71
|
+
// Process per-project registries (supports future layouts)
|
|
72
|
+
const projectsDir = join(workspaceRoot, 'projects');
|
|
73
|
+
if (existsSync(projectsDir)) {
|
|
74
|
+
try {
|
|
75
|
+
const entries = readdirSync(projectsDir);
|
|
76
|
+
for (const name of entries) {
|
|
77
|
+
const full = join(projectsDir, name);
|
|
78
|
+
try {
|
|
79
|
+
if (!statSync(full).isDirectory())
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const candidate = join(full, '.fazemos', 'roles.json');
|
|
86
|
+
if (existsSync(candidate)) {
|
|
87
|
+
try {
|
|
88
|
+
const raw = JSON.parse(readFileSync(candidate, 'utf-8'));
|
|
89
|
+
const registry = {
|
|
90
|
+
...raw,
|
|
91
|
+
_workspaceRoot: workspaceRoot,
|
|
92
|
+
_registryPath: candidate,
|
|
93
|
+
};
|
|
94
|
+
processRegistry(registry);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
if (err instanceof RosterLoadError)
|
|
98
|
+
throw err;
|
|
99
|
+
// Malformed JSON or other issues — skip silently
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
if (err instanceof RosterLoadError)
|
|
106
|
+
throw err;
|
|
107
|
+
// Can't enumerate projects/ — continue
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { declared_here, declared_cross_workspace, source_files };
|
|
111
|
+
}
|
|
112
|
+
// ── Classification helpers ─────────────────────────────────────────────────────
|
|
113
|
+
/**
|
|
114
|
+
* Return the roster classification for a (project_slug, role_slug) pair.
|
|
115
|
+
* `declared_here` wins over `declared_cross_workspace`.
|
|
116
|
+
*/
|
|
117
|
+
export function classifyRoleForProject(roster, project_slug, role_slug) {
|
|
118
|
+
if (roster.declared_here.some((e) => e.project_slug === project_slug && e.role_slug === role_slug)) {
|
|
119
|
+
return 'declared_here';
|
|
120
|
+
}
|
|
121
|
+
if (roster.declared_cross_workspace.some((e) => e.role_slug === role_slug)) {
|
|
122
|
+
return 'declared_cross_workspace';
|
|
123
|
+
}
|
|
124
|
+
return 'not_declared';
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Return all declared-here entries for a given role_slug, plus whether it is
|
|
128
|
+
* cross-workspace-declared.
|
|
129
|
+
*/
|
|
130
|
+
export function getProjectsForRole(roster, role_slug) {
|
|
131
|
+
return {
|
|
132
|
+
declared_here: roster.declared_here.filter((e) => e.role_slug === role_slug),
|
|
133
|
+
declared_cross_workspace: roster.declared_cross_workspace.find((e) => e.role_slug === role_slug) ?? null,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Return all declared-here roles for a given project_slug, plus the cross-workspace
|
|
138
|
+
* entries (which are project-agnostic — they apply to the whole workspace).
|
|
139
|
+
*/
|
|
140
|
+
export function getRolesForProject(roster, project_slug) {
|
|
141
|
+
return {
|
|
142
|
+
declared_here: roster.declared_here.filter((e) => e.project_slug === project_slug),
|
|
143
|
+
declared_cross_workspace: roster.declared_cross_workspace,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// ── Errors ────────────────────────────────────────────────────────────────────
|
|
147
|
+
export class RosterLoadError extends Error {
|
|
148
|
+
constructor(message) {
|
|
149
|
+
super(message);
|
|
150
|
+
this.name = 'RosterLoadError';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=roster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roster.js","sourceRoot":"","sources":["../../src/preflight/roster.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 1 — Agent member exists in org with the target role_slug.
|
|
3
|
+
*
|
|
4
|
+
* Data source: GET /api/organizations/:orgId/members?type=agent
|
|
5
|
+
* Checks: (a) an agent member named agentName exists, (b) role_slug ∈ agent_config.roles.
|
|
6
|
+
*/
|
|
7
|
+
import type { PreflightRow } from './schema.js';
|
|
8
|
+
export declare function checkRow1Member(orgId: string, agentName: string, roleSlug: string): Promise<PreflightRow>;
|