@formigio/fazemos-cli 0.10.43 → 0.10.45
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/dispatch.d.ts +13 -0
- package/dist/dispatch.js.map +1 -1
- package/dist/ftr.d.ts +50 -0
- package/dist/ftr.js +260 -0
- package/dist/ftr.js.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -1
- package/dist/schedule.d.ts +64 -0
- package/dist/schedule.js +528 -0
- package/dist/schedule.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F35-FU-CRON-TZ-SCHEDULE — Per-project wake schedules: CLI command helpers.
|
|
3
|
+
*
|
|
4
|
+
* Exports `registerScheduleCommands(program)` which wires the following commands
|
|
5
|
+
* into the root Commander program (mirrors the trigger/wake group pattern):
|
|
6
|
+
*
|
|
7
|
+
* fazemos schedule list [--project <slug>] [--json]
|
|
8
|
+
* → GET /api/control-plane/wake-schedules
|
|
9
|
+
* Lists all (role, cadence) schedule rows for the active/specified project.
|
|
10
|
+
*
|
|
11
|
+
* fazemos schedule set --role <slug> --cadence <daily|weekly> --at <HH:MM>
|
|
12
|
+
* --reason <text> [--on <weekday>] [--tz <IANA>]
|
|
13
|
+
* [--project <slug>] [--json]
|
|
14
|
+
* → POST /api/control-plane/wake-schedules
|
|
15
|
+
* UPSERT schedule row — re-activates if disabled. Audit reason required.
|
|
16
|
+
*
|
|
17
|
+
* fazemos schedule unset --role <slug> --cadence <daily|weekly> --reason <text>
|
|
18
|
+
* [--project <slug>] [--json]
|
|
19
|
+
* → POST /api/control-plane/wake-schedules/unset
|
|
20
|
+
* Hard-delete the schedule row.
|
|
21
|
+
*
|
|
22
|
+
* fazemos schedule disable --role <slug> --cadence <daily|weekly> --reason <text>
|
|
23
|
+
* [--project <slug>] [--json]
|
|
24
|
+
* → POST /api/control-plane/wake-schedules/disable
|
|
25
|
+
* Soft-disable (is_active=FALSE, preserves config for future re-enable).
|
|
26
|
+
*
|
|
27
|
+
* fazemos schedule enable --role <slug> --cadence <daily|weekly> --reason <text>
|
|
28
|
+
* [--project <slug>] [--json]
|
|
29
|
+
* → POST /api/control-plane/wake-schedules/enable
|
|
30
|
+
* Re-enable soft-disabled schedule. Surfaces trigger_disable_active state.
|
|
31
|
+
*
|
|
32
|
+
* fazemos schedule tz set <IANA> --reason <text> [--project <slug>] [--json]
|
|
33
|
+
* → POST /api/control-plane/projects/timezone
|
|
34
|
+
* Set project IANA timezone; response echoes updated next_fire_utc_iso
|
|
35
|
+
* for every inheriting (timezone=NULL) schedule.
|
|
36
|
+
*
|
|
37
|
+
* Auth: list → any active org member (requireMember).
|
|
38
|
+
* set/unset/disable/enable/tz set → admin or owner (requireRole).
|
|
39
|
+
*
|
|
40
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
* IMPORTANT DIFFERENCE FROM trigger.ts:
|
|
42
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
43
|
+
* trigger.ts passes `noProjectHeader: true` on EVERY call (it opted out of the
|
|
44
|
+
* X-Fazemos-Project-Id header because those shipped commands pre-date F15 header
|
|
45
|
+
* scoping). This file does NOT pass `noProjectHeader: true`. The new schedule
|
|
46
|
+
* endpoints read req.projectId from the X-Fazemos-Project-Id header from day
|
|
47
|
+
* one — this is the greenfield fix for the header inconsistency documented in
|
|
48
|
+
* F35-FU-CLI-PROJECT-HEADER-RECONCILE. No `noProjectHeader` usage here.
|
|
49
|
+
*
|
|
50
|
+
* Spec: F35-FU-CRON-TZ-SCHEDULE-per-project-wake-schedules-tech-spec.md
|
|
51
|
+
* Manifest: cli.commands (CMD-1 … CMD-6)
|
|
52
|
+
*/
|
|
53
|
+
import type { Command } from 'commander';
|
|
54
|
+
/**
|
|
55
|
+
* Register `schedule list`, `schedule set`, `schedule unset`, `schedule disable`,
|
|
56
|
+
* `schedule enable`, and `schedule tz set` into the root Commander program.
|
|
57
|
+
* Called from index.ts after `program` is created, alongside the other
|
|
58
|
+
* registerXxxCommands calls.
|
|
59
|
+
*
|
|
60
|
+
* HEADER NOTE: Unlike trigger.ts (which opts out via noProjectHeader: true),
|
|
61
|
+
* these commands rely on the standard X-Fazemos-Project-Id header path in
|
|
62
|
+
* api(). Passing --project <slug> resolves to the projectId in the header.
|
|
63
|
+
*/
|
|
64
|
+
export declare function registerScheduleCommands(program: Command): void;
|
package/dist/schedule.js
ADDED
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F35-FU-CRON-TZ-SCHEDULE — Per-project wake schedules: CLI command helpers.
|
|
3
|
+
*
|
|
4
|
+
* Exports `registerScheduleCommands(program)` which wires the following commands
|
|
5
|
+
* into the root Commander program (mirrors the trigger/wake group pattern):
|
|
6
|
+
*
|
|
7
|
+
* fazemos schedule list [--project <slug>] [--json]
|
|
8
|
+
* → GET /api/control-plane/wake-schedules
|
|
9
|
+
* Lists all (role, cadence) schedule rows for the active/specified project.
|
|
10
|
+
*
|
|
11
|
+
* fazemos schedule set --role <slug> --cadence <daily|weekly> --at <HH:MM>
|
|
12
|
+
* --reason <text> [--on <weekday>] [--tz <IANA>]
|
|
13
|
+
* [--project <slug>] [--json]
|
|
14
|
+
* → POST /api/control-plane/wake-schedules
|
|
15
|
+
* UPSERT schedule row — re-activates if disabled. Audit reason required.
|
|
16
|
+
*
|
|
17
|
+
* fazemos schedule unset --role <slug> --cadence <daily|weekly> --reason <text>
|
|
18
|
+
* [--project <slug>] [--json]
|
|
19
|
+
* → POST /api/control-plane/wake-schedules/unset
|
|
20
|
+
* Hard-delete the schedule row.
|
|
21
|
+
*
|
|
22
|
+
* fazemos schedule disable --role <slug> --cadence <daily|weekly> --reason <text>
|
|
23
|
+
* [--project <slug>] [--json]
|
|
24
|
+
* → POST /api/control-plane/wake-schedules/disable
|
|
25
|
+
* Soft-disable (is_active=FALSE, preserves config for future re-enable).
|
|
26
|
+
*
|
|
27
|
+
* fazemos schedule enable --role <slug> --cadence <daily|weekly> --reason <text>
|
|
28
|
+
* [--project <slug>] [--json]
|
|
29
|
+
* → POST /api/control-plane/wake-schedules/enable
|
|
30
|
+
* Re-enable soft-disabled schedule. Surfaces trigger_disable_active state.
|
|
31
|
+
*
|
|
32
|
+
* fazemos schedule tz set <IANA> --reason <text> [--project <slug>] [--json]
|
|
33
|
+
* → POST /api/control-plane/projects/timezone
|
|
34
|
+
* Set project IANA timezone; response echoes updated next_fire_utc_iso
|
|
35
|
+
* for every inheriting (timezone=NULL) schedule.
|
|
36
|
+
*
|
|
37
|
+
* Auth: list → any active org member (requireMember).
|
|
38
|
+
* set/unset/disable/enable/tz set → admin or owner (requireRole).
|
|
39
|
+
*
|
|
40
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
* IMPORTANT DIFFERENCE FROM trigger.ts:
|
|
42
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
43
|
+
* trigger.ts passes `noProjectHeader: true` on EVERY call (it opted out of the
|
|
44
|
+
* X-Fazemos-Project-Id header because those shipped commands pre-date F15 header
|
|
45
|
+
* scoping). This file does NOT pass `noProjectHeader: true`. The new schedule
|
|
46
|
+
* endpoints read req.projectId from the X-Fazemos-Project-Id header from day
|
|
47
|
+
* one — this is the greenfield fix for the header inconsistency documented in
|
|
48
|
+
* F35-FU-CLI-PROJECT-HEADER-RECONCILE. No `noProjectHeader` usage here.
|
|
49
|
+
*
|
|
50
|
+
* Spec: F35-FU-CRON-TZ-SCHEDULE-per-project-wake-schedules-tech-spec.md
|
|
51
|
+
* Manifest: cli.commands (CMD-1 … CMD-6)
|
|
52
|
+
*/
|
|
53
|
+
import chalk from 'chalk';
|
|
54
|
+
import { api } from './api.js';
|
|
55
|
+
// ── Helpers ────────────────────────────────────────────────────────────────────
|
|
56
|
+
/**
|
|
57
|
+
* Validate and normalize a cadence flag value.
|
|
58
|
+
* Throws a user-facing error for unsupported values.
|
|
59
|
+
*/
|
|
60
|
+
function normalizeCadence(cadence) {
|
|
61
|
+
const c = cadence.trim().toLowerCase();
|
|
62
|
+
if (c !== 'daily' && c !== 'weekly') {
|
|
63
|
+
throw new Error(`--cadence must be 'daily' or 'weekly', got: ${cadence}`);
|
|
64
|
+
}
|
|
65
|
+
return c;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Validate a local_time string (HH:MM 24h format).
|
|
69
|
+
* Throws a user-facing error for values that don't match.
|
|
70
|
+
*/
|
|
71
|
+
function validateLocalTime(value) {
|
|
72
|
+
if (!/^[0-2][0-9]:[0-5][0-9]$/.test(value)) {
|
|
73
|
+
throw new Error(`--at must be HH:MM in 24h format (e.g. 07:30, 14:00), got: ${value}`);
|
|
74
|
+
}
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Validate an ISO weekday (1=Monday … 7=Sunday, ISO 8601).
|
|
79
|
+
* Throws a user-facing error for out-of-range values.
|
|
80
|
+
*/
|
|
81
|
+
function validateWeekday(value) {
|
|
82
|
+
const n = parseInt(value, 10);
|
|
83
|
+
if (isNaN(n) || n < 1 || n > 7) {
|
|
84
|
+
throw new Error(`--on must be an ISO weekday number 1..7 (Mon=1 … Sun=7), got: ${value}`);
|
|
85
|
+
}
|
|
86
|
+
return n;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Client-side IANA timezone validation via Intl.DateTimeFormat.
|
|
90
|
+
* luxon is NOT imported into the CLI (it lives in fazemos-api); we use
|
|
91
|
+
* the native Intl API as a lightweight client-side sanity check that
|
|
92
|
+
* rejects obvious typos (e.g. "America/Denverr") before making a round-trip.
|
|
93
|
+
* The API performs authoritative validation (luxon .setZone().isValid).
|
|
94
|
+
*/
|
|
95
|
+
function validateIana(tz) {
|
|
96
|
+
try {
|
|
97
|
+
Intl.DateTimeFormat(undefined, { timeZone: tz });
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
throw new Error(`--tz "${tz}" is not a recognised IANA timezone. Check spelling (e.g. America/Denver, UTC, Europe/London).`);
|
|
101
|
+
}
|
|
102
|
+
return tz;
|
|
103
|
+
}
|
|
104
|
+
/** ISO weekday number → short name for human display. */
|
|
105
|
+
function weekdayName(n) {
|
|
106
|
+
if (n === null)
|
|
107
|
+
return '';
|
|
108
|
+
const names = ['', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
|
109
|
+
return names[n] ?? String(n);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Human-readable active/disabled label with colour.
|
|
113
|
+
*/
|
|
114
|
+
function activeLabel(row) {
|
|
115
|
+
if (row.is_active)
|
|
116
|
+
return chalk.green('active');
|
|
117
|
+
return chalk.red('disabled');
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Render a single schedule row in human-readable form.
|
|
121
|
+
*/
|
|
122
|
+
function renderScheduleRow(row) {
|
|
123
|
+
const cadenceDisplay = row.cadence === 'weekly'
|
|
124
|
+
? `weekly (${weekdayName(row.weekday)})`
|
|
125
|
+
: 'daily';
|
|
126
|
+
console.log(` ${chalk.cyan(row.role.padEnd(32))} ${cadenceDisplay.padEnd(18)} ${row.local_time} ${activeLabel(row)}`);
|
|
127
|
+
console.log(` tz: ${row.timezone}${row.timezone_inherited ? chalk.dim(' (inherited)') : ''}`);
|
|
128
|
+
console.log(` next: ${new Date(row.next_fire_utc_iso).toLocaleString()} UTC`);
|
|
129
|
+
if (!row.is_active && row.disabled_at) {
|
|
130
|
+
console.log(` disabled: ${new Date(row.disabled_at).toLocaleString()}`);
|
|
131
|
+
if (row.disabled_reason) {
|
|
132
|
+
console.log(` reason: ${chalk.dim(row.disabled_reason)}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (row.trigger_disable_active) {
|
|
136
|
+
console.log(chalk.yellow(` note: trigger disable also active — run \`fazemos trigger enable --role ${row.role} --cadence ${row.cadence}\` to fully arm`));
|
|
137
|
+
}
|
|
138
|
+
console.log(` id: ${chalk.dim(row.id)}`);
|
|
139
|
+
}
|
|
140
|
+
// ── Command registration ───────────────────────────────────────────────────────
|
|
141
|
+
/**
|
|
142
|
+
* Register `schedule list`, `schedule set`, `schedule unset`, `schedule disable`,
|
|
143
|
+
* `schedule enable`, and `schedule tz set` into the root Commander program.
|
|
144
|
+
* Called from index.ts after `program` is created, alongside the other
|
|
145
|
+
* registerXxxCommands calls.
|
|
146
|
+
*
|
|
147
|
+
* HEADER NOTE: Unlike trigger.ts (which opts out via noProjectHeader: true),
|
|
148
|
+
* these commands rely on the standard X-Fazemos-Project-Id header path in
|
|
149
|
+
* api(). Passing --project <slug> resolves to the projectId in the header.
|
|
150
|
+
*/
|
|
151
|
+
export function registerScheduleCommands(program) {
|
|
152
|
+
// ── `fazemos schedule` ───────────────────────────────────────────────────────
|
|
153
|
+
//
|
|
154
|
+
// Parent command hosting sub-commands. No action on parent itself.
|
|
155
|
+
const scheduleCmd = program
|
|
156
|
+
.command('schedule')
|
|
157
|
+
.description('Manage per-project wake schedules (AUTONOMY Phase 3 control plane).\n\n' +
|
|
158
|
+
'Sub-commands:\n' +
|
|
159
|
+
' list List schedule rows for the active project\n' +
|
|
160
|
+
' set Create or update a (role, cadence) schedule (admin/owner)\n' +
|
|
161
|
+
' unset Hard-delete a schedule row (admin/owner)\n' +
|
|
162
|
+
' disable Soft-disable a schedule (preserves config) (admin/owner)\n' +
|
|
163
|
+
' enable Re-enable a soft-disabled schedule (admin/owner)\n' +
|
|
164
|
+
' tz Project timezone sub-group\n\n' +
|
|
165
|
+
'list is readable by any active org member.\n' +
|
|
166
|
+
'All mutations require admin or owner role.\n' +
|
|
167
|
+
'All operations use the active project (or --project <slug> override).\n\n' +
|
|
168
|
+
'Unlike the trigger/wake commands, schedule commands use the\n' +
|
|
169
|
+
'X-Fazemos-Project-Id header from day one (not noProjectHeader: true).');
|
|
170
|
+
// ── `fazemos schedule list` ──────────────────────────────────────────────────
|
|
171
|
+
//
|
|
172
|
+
// GET /api/control-plane/wake-schedules
|
|
173
|
+
//
|
|
174
|
+
// Lists all (role, cadence) schedule rows for the header-scoped project.
|
|
175
|
+
// Projects without schedules show an empty state.
|
|
176
|
+
// Any active org member can read.
|
|
177
|
+
//
|
|
178
|
+
// Usage:
|
|
179
|
+
// fazemos schedule list
|
|
180
|
+
// fazemos schedule list --project <slug>
|
|
181
|
+
// fazemos schedule list --json
|
|
182
|
+
scheduleCmd
|
|
183
|
+
.command('list')
|
|
184
|
+
.description('List wake schedule rows for the active project.\n\n' +
|
|
185
|
+
'Shows each (role, cadence) row: local_time, timezone, active/disabled state,\n' +
|
|
186
|
+
'next_fire_utc_iso, and composition note if a trigger disable is also active.\n\n' +
|
|
187
|
+
'Readable by any active org member. Use --json for machine-readable output.')
|
|
188
|
+
.option('--project <slug>', 'project slug override (defaults to active project)')
|
|
189
|
+
.option('--json', 'output machine-readable JSON')
|
|
190
|
+
.action(async (opts) => {
|
|
191
|
+
try {
|
|
192
|
+
const data = await api('GET', '/api/control-plane/wake-schedules', undefined, { projectSlug: opts.project });
|
|
193
|
+
if (opts.json) {
|
|
194
|
+
console.log(JSON.stringify(data, null, 2));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const { project, schedules } = data;
|
|
198
|
+
console.log(chalk.bold(`Wake schedules for project: ${chalk.cyan(project.slug)}`));
|
|
199
|
+
console.log(` Project timezone: ${chalk.cyan(project.timezone)}`);
|
|
200
|
+
console.log();
|
|
201
|
+
if (schedules.length === 0) {
|
|
202
|
+
console.log(chalk.yellow('No wake schedules configured for this project.'));
|
|
203
|
+
console.log(chalk.dim(' Use `fazemos schedule set` to create one.'));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
console.log(chalk.bold(`Schedules (${schedules.length}):`));
|
|
207
|
+
console.log();
|
|
208
|
+
for (const row of schedules) {
|
|
209
|
+
renderScheduleRow(row);
|
|
210
|
+
console.log();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
215
|
+
console.error(chalk.red(`Error: ${msg}`));
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
// ── `fazemos schedule set` ────────────────────────────────────────────────────
|
|
220
|
+
//
|
|
221
|
+
// POST /api/control-plane/wake-schedules
|
|
222
|
+
//
|
|
223
|
+
// UPSERT on (org_id, project_id, role, cadence). Creates or updates.
|
|
224
|
+
// Re-activates a disabled row if it exists (idempotent on-disk).
|
|
225
|
+
//
|
|
226
|
+
// Client-side validation (fast-fail before API round-trip):
|
|
227
|
+
// - HH:MM regex on --at
|
|
228
|
+
// - weekday 1..7 if --on is provided
|
|
229
|
+
// - IANA check on --tz if provided
|
|
230
|
+
// - weekly cadence requires --on; daily forbids --on
|
|
231
|
+
//
|
|
232
|
+
// Usage:
|
|
233
|
+
// fazemos schedule set --role project-manager --cadence daily --at 07:30 --reason "..."
|
|
234
|
+
// fazemos schedule set --role project-manager --cadence weekly --at 08:00 --on 1 --reason "..."
|
|
235
|
+
// fazemos schedule set --role project-manager --cadence daily --at 07:30 --tz America/Denver --reason "..."
|
|
236
|
+
scheduleCmd
|
|
237
|
+
.command('set')
|
|
238
|
+
.description('Create or update a wake schedule for the active project (admin/owner only).\n\n' +
|
|
239
|
+
'UPSERT on (role, cadence) — re-activates a disabled row if one exists.\n\n' +
|
|
240
|
+
'Required: --role, --cadence, --at, --reason\n' +
|
|
241
|
+
'Conditional: --on (ISO weekday 1..7, required for weekly; omit for daily)\n' +
|
|
242
|
+
'Optional: --tz (IANA timezone override; omit to inherit project timezone)\n\n' +
|
|
243
|
+
'Examples:\n' +
|
|
244
|
+
' fazemos schedule set --role project-manager --cadence daily \\\n' +
|
|
245
|
+
' --at 07:30 --reason "Morning groom schedule"\n\n' +
|
|
246
|
+
' fazemos schedule set --role project-manager --cadence weekly --on 1 \\\n' +
|
|
247
|
+
' --at 08:00 --tz America/Denver --reason "Weekly Monday planning"\n\n' +
|
|
248
|
+
'Requires admin or owner role. --reason is mandatory (audit trail).')
|
|
249
|
+
.requiredOption('--role <slug>', 'role slug (e.g. project-manager)')
|
|
250
|
+
.requiredOption('--cadence <daily|weekly>', 'cadence (daily or weekly)')
|
|
251
|
+
.requiredOption('--at <HH:MM>', 'local fire time in 24h HH:MM format (e.g. 07:30)')
|
|
252
|
+
.requiredOption('--reason <text>', 'reason for the change (required for audit trail, ≤500 chars)')
|
|
253
|
+
.option('--on <weekday>', 'ISO weekday number 1..7 (Mon=1 … Sun=7); required for weekly cadence')
|
|
254
|
+
.option('--tz <IANA>', 'IANA timezone override (e.g. America/Denver); omit to inherit project timezone')
|
|
255
|
+
.option('--project <slug>', 'project slug override (defaults to active project)')
|
|
256
|
+
.option('--json', 'output machine-readable JSON')
|
|
257
|
+
.action(async (opts) => {
|
|
258
|
+
try {
|
|
259
|
+
// ── Client-side validation ──────────────────────────────────────────
|
|
260
|
+
const cadence = normalizeCadence(opts.cadence);
|
|
261
|
+
const local_time = validateLocalTime(opts.at);
|
|
262
|
+
let weekday = null;
|
|
263
|
+
if (cadence === 'weekly') {
|
|
264
|
+
if (opts.on === undefined) {
|
|
265
|
+
throw new Error(`--on is required for weekly cadence (ISO weekday 1..7, Mon=1 … Sun=7).`);
|
|
266
|
+
}
|
|
267
|
+
weekday = validateWeekday(opts.on);
|
|
268
|
+
}
|
|
269
|
+
else if (opts.on !== undefined) {
|
|
270
|
+
throw new Error(`--on is only valid for weekly cadence; omit it for daily.`);
|
|
271
|
+
}
|
|
272
|
+
const timezone = opts.tz !== undefined ? validateIana(opts.tz) : null;
|
|
273
|
+
const body = {
|
|
274
|
+
role: opts.role.trim().toLowerCase(),
|
|
275
|
+
cadence,
|
|
276
|
+
local_time,
|
|
277
|
+
weekday,
|
|
278
|
+
timezone,
|
|
279
|
+
reason: opts.reason,
|
|
280
|
+
};
|
|
281
|
+
const data = await api('POST', '/api/control-plane/wake-schedules', body, { projectSlug: opts.project });
|
|
282
|
+
if (opts.json) {
|
|
283
|
+
console.log(JSON.stringify(data, null, 2));
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const { schedule } = data;
|
|
287
|
+
console.log(chalk.green(`✓ Schedule set: ${chalk.cyan(schedule.role)} / ${schedule.cadence}`));
|
|
288
|
+
console.log(` At: ${schedule.local_time}${schedule.timezone_inherited ? '' : ` (tz: ${schedule.timezone})`}`);
|
|
289
|
+
console.log(` Timezone: ${schedule.timezone}${schedule.timezone_inherited ? chalk.dim(' (inherited from project)') : ''}`);
|
|
290
|
+
console.log(` Next: ${new Date(schedule.next_fire_utc_iso).toLocaleString()} UTC`);
|
|
291
|
+
console.log(` Status: ${activeLabel(schedule)}`);
|
|
292
|
+
console.log(` ID: ${chalk.dim(schedule.id)}`);
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
296
|
+
console.error(chalk.red(`Error: ${msg}`));
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
// ── `fazemos schedule unset` ──────────────────────────────────────────────────
|
|
301
|
+
//
|
|
302
|
+
// POST /api/control-plane/wake-schedules/unset
|
|
303
|
+
//
|
|
304
|
+
// Hard-delete: row is removed from project_wake_schedules. The trigger engine
|
|
305
|
+
// will stop enumerating this (role, cadence) for this project on the next tick.
|
|
306
|
+
// Use `schedule disable` if you want to preserve the config and re-enable later.
|
|
307
|
+
//
|
|
308
|
+
// Usage:
|
|
309
|
+
// fazemos schedule unset --role project-manager --cadence daily --reason "Removing schedule"
|
|
310
|
+
scheduleCmd
|
|
311
|
+
.command('unset')
|
|
312
|
+
.description('Hard-delete a wake schedule row (admin/owner only).\n\n' +
|
|
313
|
+
'Permanently removes the (role, cadence) row from this project\'s schedule\n' +
|
|
314
|
+
'table. The trigger engine stops enumerating it on the next sweep tick.\n\n' +
|
|
315
|
+
'TIP: Use `fazemos schedule disable` if you want to preserve the config\n' +
|
|
316
|
+
'and re-enable later without re-entering the time/timezone.\n\n' +
|
|
317
|
+
'Requires admin or owner role. --reason is mandatory (audit trail).')
|
|
318
|
+
.requiredOption('--role <slug>', 'role slug (e.g. project-manager)')
|
|
319
|
+
.requiredOption('--cadence <daily|weekly>', 'cadence to unset (daily or weekly)')
|
|
320
|
+
.requiredOption('--reason <text>', 'reason for the deletion (required for audit trail)')
|
|
321
|
+
.option('--project <slug>', 'project slug override (defaults to active project)')
|
|
322
|
+
.option('--json', 'output machine-readable JSON')
|
|
323
|
+
.action(async (opts) => {
|
|
324
|
+
try {
|
|
325
|
+
const cadence = normalizeCadence(opts.cadence);
|
|
326
|
+
const body = {
|
|
327
|
+
role: opts.role.trim().toLowerCase(),
|
|
328
|
+
cadence,
|
|
329
|
+
reason: opts.reason,
|
|
330
|
+
};
|
|
331
|
+
const data = await api('POST', '/api/control-plane/wake-schedules/unset', body, { projectSlug: opts.project });
|
|
332
|
+
if (opts.json) {
|
|
333
|
+
console.log(JSON.stringify(data, null, 2));
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if (data.deleted) {
|
|
337
|
+
console.log(chalk.red(`✗ Schedule unset: ${chalk.cyan(data.role)} / ${data.cadence}`));
|
|
338
|
+
console.log(` The row has been permanently removed from the schedule table.`);
|
|
339
|
+
console.log(chalk.dim(` Use \`fazemos schedule set\` to recreate it.`));
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
console.log(chalk.yellow(`No schedule found for ${opts.role} / ${cadence} — nothing removed.`));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (err) {
|
|
346
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
347
|
+
console.error(chalk.red(`Error: ${msg}`));
|
|
348
|
+
process.exit(1);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
// ── `fazemos schedule disable` ────────────────────────────────────────────────
|
|
352
|
+
//
|
|
353
|
+
// POST /api/control-plane/wake-schedules/disable
|
|
354
|
+
//
|
|
355
|
+
// Soft-disable: sets is_active=FALSE, disabled_at=now(), disabled_reason=<reason>.
|
|
356
|
+
// The row is preserved. Use `schedule enable` to re-activate without losing config.
|
|
357
|
+
//
|
|
358
|
+
// Usage:
|
|
359
|
+
// fazemos schedule disable --role project-manager --cadence daily --reason "Q2 freeze"
|
|
360
|
+
scheduleCmd
|
|
361
|
+
.command('disable')
|
|
362
|
+
.description('Soft-disable a wake schedule row (admin/owner only).\n\n' +
|
|
363
|
+
'Sets is_active=FALSE on the (role, cadence) row. The trigger engine stops\n' +
|
|
364
|
+
'enumerating it, but the row is preserved with its local_time/timezone config.\n' +
|
|
365
|
+
'Re-activate with `fazemos schedule enable`.\n\n' +
|
|
366
|
+
'Requires admin or owner role. --reason is mandatory (audit trail).')
|
|
367
|
+
.requiredOption('--role <slug>', 'role slug (e.g. project-manager)')
|
|
368
|
+
.requiredOption('--cadence <daily|weekly>', 'cadence to disable (daily or weekly)')
|
|
369
|
+
.requiredOption('--reason <text>', 'reason for the disable (required for audit trail)')
|
|
370
|
+
.option('--project <slug>', 'project slug override (defaults to active project)')
|
|
371
|
+
.option('--json', 'output machine-readable JSON')
|
|
372
|
+
.action(async (opts) => {
|
|
373
|
+
try {
|
|
374
|
+
const cadence = normalizeCadence(opts.cadence);
|
|
375
|
+
const body = {
|
|
376
|
+
role: opts.role.trim().toLowerCase(),
|
|
377
|
+
cadence,
|
|
378
|
+
reason: opts.reason,
|
|
379
|
+
};
|
|
380
|
+
const data = await api('POST', '/api/control-plane/wake-schedules/disable', body, { projectSlug: opts.project });
|
|
381
|
+
if (opts.json) {
|
|
382
|
+
console.log(JSON.stringify(data, null, 2));
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const { schedule } = data;
|
|
386
|
+
console.log(chalk.red(`⏸ Schedule disabled: ${chalk.cyan(schedule.role)} / ${schedule.cadence}`));
|
|
387
|
+
console.log(` Config preserved — use \`fazemos schedule enable\` to re-activate.`);
|
|
388
|
+
if (schedule.disabled_at) {
|
|
389
|
+
console.log(` Disabled at: ${new Date(schedule.disabled_at).toLocaleString()}`);
|
|
390
|
+
}
|
|
391
|
+
console.log(` Reason: ${opts.reason}`);
|
|
392
|
+
}
|
|
393
|
+
catch (err) {
|
|
394
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
395
|
+
console.error(chalk.red(`Error: ${msg}`));
|
|
396
|
+
process.exit(1);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
// ── `fazemos schedule enable` ─────────────────────────────────────────────────
|
|
400
|
+
//
|
|
401
|
+
// POST /api/control-plane/wake-schedules/enable
|
|
402
|
+
//
|
|
403
|
+
// Re-enable: sets is_active=TRUE, disabled_at=NULL, disabled_reason=NULL.
|
|
404
|
+
// Response includes trigger_disable_active — if a trigger_disables row also
|
|
405
|
+
// exists for (org, role, cadence), the schedule is enabled but the trigger engine
|
|
406
|
+
// won't fire until that disable is also cleared.
|
|
407
|
+
//
|
|
408
|
+
// Usage:
|
|
409
|
+
// fazemos schedule enable --role project-manager --cadence daily --reason "Resuming after freeze"
|
|
410
|
+
scheduleCmd
|
|
411
|
+
.command('enable')
|
|
412
|
+
.description('Re-enable a soft-disabled wake schedule row (admin/owner only).\n\n' +
|
|
413
|
+
'Sets is_active=TRUE on the (role, cadence) row. The trigger engine resumes\n' +
|
|
414
|
+
'enumerating it on the next sweep tick (≤5 min).\n\n' +
|
|
415
|
+
'NOTE: If a trigger disable is also active for this (role, cadence), both must\n' +
|
|
416
|
+
'be cleared before the schedule fires. The enable response surfaces this state:\n' +
|
|
417
|
+
'if trigger_disable_active=true, also run `fazemos trigger enable --role X --cadence Y`.\n\n' +
|
|
418
|
+
'Requires admin or owner role. --reason is mandatory (audit trail).')
|
|
419
|
+
.requiredOption('--role <slug>', 'role slug (e.g. project-manager)')
|
|
420
|
+
.requiredOption('--cadence <daily|weekly>', 'cadence to enable (daily or weekly)')
|
|
421
|
+
.requiredOption('--reason <text>', 'reason for re-enabling (required for audit trail)')
|
|
422
|
+
.option('--project <slug>', 'project slug override (defaults to active project)')
|
|
423
|
+
.option('--json', 'output machine-readable JSON')
|
|
424
|
+
.action(async (opts) => {
|
|
425
|
+
try {
|
|
426
|
+
const cadence = normalizeCadence(opts.cadence);
|
|
427
|
+
const body = {
|
|
428
|
+
role: opts.role.trim().toLowerCase(),
|
|
429
|
+
cadence,
|
|
430
|
+
reason: opts.reason,
|
|
431
|
+
};
|
|
432
|
+
const data = await api('POST', '/api/control-plane/wake-schedules/enable', body, { projectSlug: opts.project });
|
|
433
|
+
if (opts.json) {
|
|
434
|
+
console.log(JSON.stringify(data, null, 2));
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const { schedule, trigger_disable_active } = data;
|
|
438
|
+
console.log(chalk.green(`▶ Schedule enabled: ${chalk.cyan(schedule.role)} / ${schedule.cadence}`));
|
|
439
|
+
console.log(` At: ${schedule.local_time} (${schedule.timezone})`);
|
|
440
|
+
console.log(` Next: ${new Date(schedule.next_fire_utc_iso).toLocaleString()} UTC`);
|
|
441
|
+
console.log(` Reason: ${opts.reason}`);
|
|
442
|
+
// Composition note: EDGE-8 — trigger_disable_active=true means the schedule
|
|
443
|
+
// is now enabled at the schedule level but a trigger_disables row is also
|
|
444
|
+
// active, which will still suppress fires.
|
|
445
|
+
if (trigger_disable_active) {
|
|
446
|
+
console.log();
|
|
447
|
+
console.log(chalk.yellow(` note: schedule is enabled but a trigger disable is also active;\n` +
|
|
448
|
+
` run \`fazemos trigger enable --role ${schedule.role} --cadence ${schedule.cadence}\` to fully arm.`));
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
console.log(chalk.dim(` The trigger engine will evaluate this schedule on the next sweep tick (≤5 min).`));
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
catch (err) {
|
|
455
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
456
|
+
console.error(chalk.red(`Error: ${msg}`));
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
// ── `fazemos schedule tz` ─────────────────────────────────────────────────────
|
|
461
|
+
//
|
|
462
|
+
// Parent for project timezone sub-commands.
|
|
463
|
+
const tzCmd = scheduleCmd
|
|
464
|
+
.command('tz')
|
|
465
|
+
.description('Project timezone sub-commands.\n\n' +
|
|
466
|
+
'Sub-commands:\n' +
|
|
467
|
+
' set <IANA> Set the project\'s IANA timezone (admin/owner)\n\n' +
|
|
468
|
+
'All inheriting schedules (timezone=NULL) immediately resolve to the new zone.\n' +
|
|
469
|
+
'Explicitly-overridden schedules (--tz on `schedule set`) are unaffected.');
|
|
470
|
+
// ── `fazemos schedule tz set <IANA>` ─────────────────────────────────────────
|
|
471
|
+
//
|
|
472
|
+
// POST /api/control-plane/projects/timezone
|
|
473
|
+
//
|
|
474
|
+
// Sets projects.timezone for the header-scoped project.
|
|
475
|
+
// Every schedule with timezone=NULL starts resolving to the new zone on the
|
|
476
|
+
// next sweep tick. Response includes schedules_updated[] with the new
|
|
477
|
+
// next_fire_utc_iso for each affected (inheriting) schedule.
|
|
478
|
+
//
|
|
479
|
+
// Usage:
|
|
480
|
+
// fazemos schedule tz set America/Denver --reason "Aligning project to Denver office TZ"
|
|
481
|
+
// fazemos schedule tz set UTC --reason "Reset to UTC default"
|
|
482
|
+
tzCmd
|
|
483
|
+
.command('set <IANA>')
|
|
484
|
+
.description('Set the project\'s IANA timezone (admin/owner only).\n\n' +
|
|
485
|
+
'Updates projects.timezone for the active project. All wake schedule rows\n' +
|
|
486
|
+
'with no explicit timezone override (timezone=NULL) immediately resolve to\n' +
|
|
487
|
+
'the new zone — next_fire_utc_iso shifts accordingly.\n\n' +
|
|
488
|
+
'Example: fazemos schedule tz set America/Denver --reason "Moving to MT"\n\n' +
|
|
489
|
+
'Requires admin or owner role. --reason is mandatory (audit trail).\n' +
|
|
490
|
+
'See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for valid values.')
|
|
491
|
+
.requiredOption('--reason <text>', 'reason for the timezone change (required for audit trail)')
|
|
492
|
+
.option('--project <slug>', 'project slug override (defaults to active project)')
|
|
493
|
+
.option('--json', 'output machine-readable JSON')
|
|
494
|
+
.action(async (iana, opts) => {
|
|
495
|
+
try {
|
|
496
|
+
// Client-side IANA validation before API round-trip
|
|
497
|
+
const timezone = validateIana(iana);
|
|
498
|
+
const body = {
|
|
499
|
+
timezone,
|
|
500
|
+
reason: opts.reason,
|
|
501
|
+
};
|
|
502
|
+
const data = await api('POST', '/api/control-plane/projects/timezone', body, { projectSlug: opts.project });
|
|
503
|
+
if (opts.json) {
|
|
504
|
+
console.log(JSON.stringify(data, null, 2));
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
const { project, schedules_updated } = data;
|
|
508
|
+
console.log(chalk.green(`✓ Project timezone set: ${chalk.cyan(project.slug)} → ${chalk.cyan(project.timezone)}`));
|
|
509
|
+
console.log();
|
|
510
|
+
if (schedules_updated.length === 0) {
|
|
511
|
+
console.log(chalk.dim(' No inheriting schedules found (all schedules have explicit timezone overrides).'));
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
console.log(chalk.bold(` Next fires (updated — ${schedules_updated.length} inheriting schedule${schedules_updated.length === 1 ? '' : 's'}):`));
|
|
515
|
+
console.log();
|
|
516
|
+
for (const s of schedules_updated) {
|
|
517
|
+
console.log(` ${chalk.cyan(s.role.padEnd(32))} ${s.cadence.padEnd(8)} → ${new Date(s.next_fire_utc_iso).toLocaleString()} UTC`);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
523
|
+
console.error(chalk.red(`Error: ${msg}`));
|
|
524
|
+
process.exit(1);
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
//# sourceMappingURL=schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.js","sourceRoot":"","sources":["../src/schedule.ts"],"names":[],"mappings":"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"}
|