@klevar/portal-cli 0.1.20 → 0.1.21

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.
@@ -28,6 +28,12 @@ export declare const CLI_EXEMPTIONS: readonly [{
28
28
  readonly reason: "Inbound webhook consumer called by Klevar Docs, not by operators or clients.";
29
29
  readonly owner: "Klevar Docs";
30
30
  readonly trackedAs: "Phase 17 inbound-webhook exemption";
31
+ }, {
32
+ readonly method: "GET";
33
+ readonly path: "/api/portal/projects/:id/timeline";
34
+ readonly reason: "Client-facing timeline used by the portal project UI; admin/operator timeline CLI already covers recall workflows.";
35
+ readonly owner: "Klevar Portal";
36
+ readonly trackedAs: "Phase 17 client timeline portal-ui exemption";
31
37
  }, {
32
38
  readonly method: "GET";
33
39
  readonly path: "/api/portal/projects/:projectId/recurring-checkpoints";
@@ -34,6 +34,13 @@ export const CLI_EXEMPTIONS = [
34
34
  owner: 'Klevar Docs',
35
35
  trackedAs: 'Phase 17 inbound-webhook exemption',
36
36
  },
37
+ {
38
+ method: 'GET',
39
+ path: '/api/portal/projects/:id/timeline',
40
+ reason: 'Client-facing timeline used by the portal project UI; admin/operator timeline CLI already covers recall workflows.',
41
+ owner: 'Klevar Portal',
42
+ trackedAs: 'Phase 17 client timeline portal-ui exemption',
43
+ },
37
44
  {
38
45
  method: 'GET',
39
46
  path: '/api/portal/projects/:projectId/recurring-checkpoints',
@@ -1 +1 @@
1
- {"version":3,"file":"_exemptions.js","sourceRoot":"","sources":["../../commands/_exemptions.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,uEAAuE;QAC/E,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,uEAAuE;QAC/E,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,0GAA0G;QAClH,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,uBAAuB;QAC7B,MAAM,EAAE,yGAAyG;QACjH,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,qCAAqC;KACjD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,qCAAqC;QAC3C,MAAM,EAAE,8EAA8E;QACtF,KAAK,EAAE,aAAa;QACpB,SAAS,EAAE,oCAAoC;KAChD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,uDAAuD;QAC7D,MAAM,EAAE,qFAAqF;QAC7F,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,uDAAuD;QAC7D,MAAM,EAAE,uFAAuF;QAC/F,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,8CAA8C;QACpD,MAAM,EAAE,wDAAwD;QAChE,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,8CAA8C;QACpD,MAAM,EAAE,uDAAuD;QAC/D,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,mDAAmD;QACzD,MAAM,EAAE,yDAAyD;QACjE,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;CACO,CAAC"}
1
+ {"version":3,"file":"_exemptions.js","sourceRoot":"","sources":["../../commands/_exemptions.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,uEAAuE;QAC/E,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,uEAAuE;QAC/E,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,0GAA0G;QAClH,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,yCAAyC;KACrD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,uBAAuB;QAC7B,MAAM,EAAE,yGAAyG;QACjH,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,qCAAqC;KACjD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,qCAAqC;QAC3C,MAAM,EAAE,8EAA8E;QACtF,KAAK,EAAE,aAAa;QACpB,SAAS,EAAE,oCAAoC;KAChD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,mCAAmC;QACzC,MAAM,EAAE,oHAAoH;QAC5H,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,8CAA8C;KAC1D;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,uDAAuD;QAC7D,MAAM,EAAE,qFAAqF;QAC7F,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,uDAAuD;QAC7D,MAAM,EAAE,uFAAuF;QAC/F,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,8CAA8C;QACpD,MAAM,EAAE,wDAAwD;QAChE,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,8CAA8C;QACpD,MAAM,EAAE,uDAAuD;QAC/D,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,mDAAmD;QACzD,MAAM,EAAE,yDAAyD;QACjE,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,wCAAwC;KACpD;CACO,CAAC"}
@@ -522,6 +522,143 @@ export declare const COMMAND_GROUPS: {
522
522
  description: string;
523
523
  };
524
524
  };
525
+ operator: {
526
+ inbox: {
527
+ method: "GET";
528
+ path: string;
529
+ auth: "apiKey";
530
+ description: string;
531
+ queryParams: string[];
532
+ };
533
+ 'inbox.mark-read': {
534
+ method: "POST";
535
+ path: string;
536
+ auth: "apiKey";
537
+ description: string;
538
+ };
539
+ 'inbox.mark-client-read': {
540
+ method: "POST";
541
+ path: string;
542
+ auth: "apiKey";
543
+ description: string;
544
+ };
545
+ 'inbox.mark-project-read': {
546
+ method: "POST";
547
+ path: string;
548
+ auth: "apiKey";
549
+ description: string;
550
+ };
551
+ 'inbox.mark-all-read': {
552
+ method: "POST";
553
+ path: string;
554
+ auth: "apiKey";
555
+ description: string;
556
+ };
557
+ 'reports.monthly': {
558
+ method: "GET";
559
+ path: string;
560
+ auth: "apiKey";
561
+ description: string;
562
+ queryParams: string[];
563
+ };
564
+ 'client.timeline': {
565
+ method: "GET";
566
+ path: string;
567
+ auth: "apiKey";
568
+ description: string;
569
+ queryParams: string[];
570
+ };
571
+ 'project.timeline': {
572
+ method: "GET";
573
+ path: string;
574
+ auth: "apiKey";
575
+ description: string;
576
+ queryParams: string[];
577
+ };
578
+ 'ops-health': {
579
+ method: "GET";
580
+ path: string;
581
+ auth: "apiKey";
582
+ description: string;
583
+ };
584
+ 'smoke.portal': {
585
+ method: "GET";
586
+ path: string;
587
+ auth: "apiKey";
588
+ description: string;
589
+ };
590
+ 'smoke.docs': {
591
+ method: "GET";
592
+ path: string;
593
+ auth: "apiKey";
594
+ description: string;
595
+ };
596
+ 'smoke.capacity': {
597
+ method: "GET";
598
+ path: string;
599
+ auth: "apiKey";
600
+ description: string;
601
+ };
602
+ 'smoke.recurring': {
603
+ method: "GET";
604
+ path: string;
605
+ auth: "apiKey";
606
+ description: string;
607
+ };
608
+ 'smoke.notifications': {
609
+ method: "GET";
610
+ path: string;
611
+ auth: "apiKey";
612
+ description: string;
613
+ };
614
+ 'clients.notifications.get': {
615
+ method: "GET";
616
+ path: string;
617
+ auth: "apiKey";
618
+ description: string;
619
+ };
620
+ 'clients.notifications.update': {
621
+ method: "PATCH";
622
+ path: string;
623
+ auth: "apiKey";
624
+ description: string;
625
+ body: string[];
626
+ };
627
+ 'projects.notifications.get': {
628
+ method: "GET";
629
+ path: string;
630
+ auth: "apiKey";
631
+ description: string;
632
+ };
633
+ 'projects.notifications.update': {
634
+ method: "PATCH";
635
+ path: string;
636
+ auth: "apiKey";
637
+ description: string;
638
+ body: string[];
639
+ };
640
+ 'notifications.preview': {
641
+ method: "GET";
642
+ path: string;
643
+ auth: "apiKey";
644
+ description: string;
645
+ queryParams: string[];
646
+ };
647
+ 'audit.list': {
648
+ method: "GET";
649
+ path: string;
650
+ auth: "apiKey";
651
+ description: string;
652
+ queryParams: string[];
653
+ };
654
+ 'audit.target': {
655
+ method: "GET";
656
+ path: string;
657
+ auth: "apiKey";
658
+ description: string;
659
+ queryParams: string[];
660
+ };
661
+ };
525
662
  notes: {
526
663
  'notes.list': {
527
664
  method: "GET";
@@ -3,6 +3,7 @@ import { docsCommands } from './docs.js';
3
3
  import { capacityCommands } from './capacity.js';
4
4
  import { metricCommands } from './metrics.js';
5
5
  import { onboardingCommands } from './onboarding.js';
6
+ import { operatorCommands } from './operator.js';
6
7
  import { noteCommands } from './notes.js';
7
8
  import { portalCommands } from './portal.js';
8
9
  import { projectCommands } from './projects.js';
@@ -20,6 +21,7 @@ export const COMMAND_GROUPS = {
20
21
  usage: usageCommands,
21
22
  updates: updateCommands,
22
23
  onboarding: onboardingCommands,
24
+ operator: operatorCommands,
23
25
  notes: noteCommands,
24
26
  recurring: recurringCommands,
25
27
  metrics: metricCommands,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAK9C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,cAAc;IACtB,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,eAAe;IACzB,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE,gBAAgB;IAC1B,KAAK,EAAE,aAAa;IACpB,OAAO,EAAE,cAAc;IACvB,UAAU,EAAE,kBAAkB;IAC9B,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,cAAc;IACvB,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,cAAc;CACgB,CAAC;AAEzC,MAAM,CAAC,MAAM,QAAQ,GAA+B,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAK9C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,cAAc;IACtB,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,eAAe;IACzB,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE,gBAAgB;IAC1B,KAAK,EAAE,aAAa;IACpB,OAAO,EAAE,cAAc;IACvB,UAAU,EAAE,kBAAkB;IAC9B,QAAQ,EAAE,gBAAgB;IAC1B,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,cAAc;IACvB,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,cAAc;CACgB,CAAC;AAEzC,MAAM,CAAC,MAAM,QAAQ,GAA+B,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC"}
@@ -0,0 +1,137 @@
1
+ export declare const operatorCommands: {
2
+ inbox: {
3
+ method: "GET";
4
+ path: string;
5
+ auth: "apiKey";
6
+ description: string;
7
+ queryParams: string[];
8
+ };
9
+ 'inbox.mark-read': {
10
+ method: "POST";
11
+ path: string;
12
+ auth: "apiKey";
13
+ description: string;
14
+ };
15
+ 'inbox.mark-client-read': {
16
+ method: "POST";
17
+ path: string;
18
+ auth: "apiKey";
19
+ description: string;
20
+ };
21
+ 'inbox.mark-project-read': {
22
+ method: "POST";
23
+ path: string;
24
+ auth: "apiKey";
25
+ description: string;
26
+ };
27
+ 'inbox.mark-all-read': {
28
+ method: "POST";
29
+ path: string;
30
+ auth: "apiKey";
31
+ description: string;
32
+ };
33
+ 'reports.monthly': {
34
+ method: "GET";
35
+ path: string;
36
+ auth: "apiKey";
37
+ description: string;
38
+ queryParams: string[];
39
+ };
40
+ 'client.timeline': {
41
+ method: "GET";
42
+ path: string;
43
+ auth: "apiKey";
44
+ description: string;
45
+ queryParams: string[];
46
+ };
47
+ 'project.timeline': {
48
+ method: "GET";
49
+ path: string;
50
+ auth: "apiKey";
51
+ description: string;
52
+ queryParams: string[];
53
+ };
54
+ 'ops-health': {
55
+ method: "GET";
56
+ path: string;
57
+ auth: "apiKey";
58
+ description: string;
59
+ };
60
+ 'smoke.portal': {
61
+ method: "GET";
62
+ path: string;
63
+ auth: "apiKey";
64
+ description: string;
65
+ };
66
+ 'smoke.docs': {
67
+ method: "GET";
68
+ path: string;
69
+ auth: "apiKey";
70
+ description: string;
71
+ };
72
+ 'smoke.capacity': {
73
+ method: "GET";
74
+ path: string;
75
+ auth: "apiKey";
76
+ description: string;
77
+ };
78
+ 'smoke.recurring': {
79
+ method: "GET";
80
+ path: string;
81
+ auth: "apiKey";
82
+ description: string;
83
+ };
84
+ 'smoke.notifications': {
85
+ method: "GET";
86
+ path: string;
87
+ auth: "apiKey";
88
+ description: string;
89
+ };
90
+ 'clients.notifications.get': {
91
+ method: "GET";
92
+ path: string;
93
+ auth: "apiKey";
94
+ description: string;
95
+ };
96
+ 'clients.notifications.update': {
97
+ method: "PATCH";
98
+ path: string;
99
+ auth: "apiKey";
100
+ description: string;
101
+ body: string[];
102
+ };
103
+ 'projects.notifications.get': {
104
+ method: "GET";
105
+ path: string;
106
+ auth: "apiKey";
107
+ description: string;
108
+ };
109
+ 'projects.notifications.update': {
110
+ method: "PATCH";
111
+ path: string;
112
+ auth: "apiKey";
113
+ description: string;
114
+ body: string[];
115
+ };
116
+ 'notifications.preview': {
117
+ method: "GET";
118
+ path: string;
119
+ auth: "apiKey";
120
+ description: string;
121
+ queryParams: string[];
122
+ };
123
+ 'audit.list': {
124
+ method: "GET";
125
+ path: string;
126
+ auth: "apiKey";
127
+ description: string;
128
+ queryParams: string[];
129
+ };
130
+ 'audit.target': {
131
+ method: "GET";
132
+ path: string;
133
+ auth: "apiKey";
134
+ description: string;
135
+ queryParams: string[];
136
+ };
137
+ };
@@ -0,0 +1,138 @@
1
+ export const operatorCommands = {
2
+ inbox: {
3
+ method: 'GET',
4
+ path: '/api/admin/operator-inbox',
5
+ auth: 'apiKey',
6
+ description: 'Review operator inbox',
7
+ queryParams: ['clientId|client', 'projectId|project', 'since', 'unreadOnly|unread', 'limit'],
8
+ },
9
+ 'inbox.mark-read': {
10
+ method: 'POST',
11
+ path: '/api/admin/operator-inbox/read/:itemId',
12
+ auth: 'apiKey',
13
+ description: 'Mark one inbox item read',
14
+ },
15
+ 'inbox.mark-client-read': {
16
+ method: 'POST',
17
+ path: '/api/admin/operator-inbox/read-client/:clientId',
18
+ auth: 'apiKey',
19
+ description: 'Mark a client inbox section read',
20
+ },
21
+ 'inbox.mark-project-read': {
22
+ method: 'POST',
23
+ path: '/api/admin/operator-inbox/read-project/:projectId',
24
+ auth: 'apiKey',
25
+ description: 'Mark a project inbox section read',
26
+ },
27
+ 'inbox.mark-all-read': {
28
+ method: 'POST',
29
+ path: '/api/admin/operator-inbox/read-all',
30
+ auth: 'apiKey',
31
+ description: 'Mark all current inbox items read',
32
+ },
33
+ 'reports.monthly': {
34
+ method: 'GET',
35
+ path: '/api/admin/clients/:clientId/reports/monthly',
36
+ auth: 'apiKey',
37
+ description: 'Generate monthly client report',
38
+ queryParams: ['period'],
39
+ },
40
+ 'client.timeline': {
41
+ method: 'GET',
42
+ path: '/api/admin/clients/:clientId/timeline',
43
+ auth: 'apiKey',
44
+ description: 'Show client timeline',
45
+ queryParams: ['projectId|project', 'type', 'since', 'until', 'limit'],
46
+ },
47
+ 'project.timeline': {
48
+ method: 'GET',
49
+ path: '/api/admin/projects/:projectId/timeline',
50
+ auth: 'apiKey',
51
+ description: 'Show project timeline',
52
+ queryParams: ['type', 'since', 'until', 'limit'],
53
+ },
54
+ 'ops-health': {
55
+ method: 'GET',
56
+ path: '/api/admin/ops-health',
57
+ auth: 'apiKey',
58
+ description: 'Show operational health summary',
59
+ },
60
+ 'smoke.portal': {
61
+ method: 'GET',
62
+ path: '/api/admin/clients/:id',
63
+ auth: 'apiKey',
64
+ description: 'Read-only portal smoke check',
65
+ },
66
+ 'smoke.docs': {
67
+ method: 'GET',
68
+ path: '/api/admin/clients/:id/docs/documents',
69
+ auth: 'apiKey',
70
+ description: 'Read-only Docs smoke check',
71
+ },
72
+ 'smoke.capacity': {
73
+ method: 'GET',
74
+ path: '/api/admin/projects/:projectId/capacity-summary',
75
+ auth: 'apiKey',
76
+ description: 'Read-only capacity smoke check',
77
+ },
78
+ 'smoke.recurring': {
79
+ method: 'GET',
80
+ path: '/api/admin/projects/:projectId/recurring-checkpoints',
81
+ auth: 'apiKey',
82
+ description: 'Read-only recurring smoke check',
83
+ },
84
+ 'smoke.notifications': {
85
+ method: 'GET',
86
+ path: '/api/admin/smoke/notifications/:clientId',
87
+ auth: 'apiKey',
88
+ description: 'Read-only notification smoke check',
89
+ },
90
+ 'clients.notifications.get': {
91
+ method: 'GET',
92
+ path: '/api/admin/clients/:id/notification-preferences',
93
+ auth: 'apiKey',
94
+ description: 'Show client notification preferences',
95
+ },
96
+ 'clients.notifications.update': {
97
+ method: 'PATCH',
98
+ path: '/api/admin/clients/:id/notification-preferences',
99
+ auth: 'apiKey',
100
+ description: 'Update client notification preferences',
101
+ body: ['mode', 'digestFrequency'],
102
+ },
103
+ 'projects.notifications.get': {
104
+ method: 'GET',
105
+ path: '/api/admin/projects/:id/notification-preferences',
106
+ auth: 'apiKey',
107
+ description: 'Show project notification preferences',
108
+ },
109
+ 'projects.notifications.update': {
110
+ method: 'PATCH',
111
+ path: '/api/admin/projects/:id/notification-preferences',
112
+ auth: 'apiKey',
113
+ description: 'Update project notification preferences',
114
+ body: ['mode', 'digestFrequency'],
115
+ },
116
+ 'notifications.preview': {
117
+ method: 'GET',
118
+ path: '/api/admin/notifications/preview/:eventType',
119
+ auth: 'apiKey',
120
+ description: 'Preview notification rendering without sending',
121
+ queryParams: ['clientId|client', 'projectId|project'],
122
+ },
123
+ 'audit.list': {
124
+ method: 'GET',
125
+ path: '/api/admin/audit-events',
126
+ auth: 'apiKey',
127
+ description: 'List operational audit events',
128
+ queryParams: ['clientId|client', 'projectId|project', 'actorId|actor', 'action', 'targetType', 'targetId', 'since', 'until', 'limit'],
129
+ },
130
+ 'audit.target': {
131
+ method: 'GET',
132
+ path: '/api/admin/audit-events',
133
+ auth: 'apiKey',
134
+ description: 'List audit events for one target',
135
+ queryParams: ['targetType', 'targetId', 'limit'],
136
+ },
137
+ };
138
+ //# sourceMappingURL=operator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operator.js","sourceRoot":"","sources":["../../commands/operator.ts"],"names":[],"mappings":"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"}
@@ -299,6 +299,42 @@ function interpolatePath(template, id) {
299
299
  return template.replace(':id', id);
300
300
  }
301
301
 
302
+ function isUuid(value) {
303
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
304
+ }
305
+
306
+ function looksLikeOpaqueId(value) {
307
+ return isUuid(value) || /^[a-z]+-\d+$/i.test(value);
308
+ }
309
+
310
+ function pathParamEntity(commandKey, paramName) {
311
+ if (paramName.toLowerCase().includes('client')) return 'client';
312
+ if (paramName.toLowerCase().includes('project')) return 'project';
313
+ if (paramName === 'id' && commandKey.startsWith('clients.')) return 'client';
314
+ if (paramName === 'id' && commandKey.startsWith('projects.')) return 'project';
315
+ return null;
316
+ }
317
+
318
+ async function resolveNameParam(commandKey, paramName, value, flags) {
319
+ if (!value || looksLikeOpaqueId(value)) return value;
320
+ const entity = pathParamEntity(commandKey, paramName);
321
+ if (!entity) return value;
322
+ const params = new URLSearchParams({ q: value, type: entity, limit: '10' });
323
+ if (entity === 'project' && flags.client) params.set('client', flags.client);
324
+ if (entity === 'project' && flags.clientId) params.set('clientId', flags.clientId);
325
+ const data = await api('GET', `/api/admin/search?${params.toString()}`);
326
+ const rows = entity === 'client' ? (data.clients || []) : (data.projects || []);
327
+ const exact = rows.filter((row) => (row.name || '').toLowerCase() === value.toLowerCase());
328
+ const candidates = exact.length > 0 ? exact : rows;
329
+ if (candidates.length === 1) return candidates[0].id;
330
+ if (candidates.length === 0) console.error(`No ${entity} found for "${value}".`);
331
+ else {
332
+ console.error(`Ambiguous ${entity} name "${value}". Use an ID or narrow the search.`);
333
+ for (const row of candidates.slice(0, 5)) console.error(` ${row.name} [${row.id}]`);
334
+ }
335
+ exitGracefully(2);
336
+ }
337
+
302
338
  const HELP_ENUMS = {
303
339
  priority: 'low|normal|high|urgent',
304
340
  submittedBy: 'client|admin|va|system',
@@ -323,6 +359,8 @@ const HELP_ENUMS = {
323
359
  owner: 'admin|client|shared',
324
360
  requiresClientAcceptance: 'true|false',
325
361
  requiresAdminAcceptance: 'true|false',
362
+ mode: 'muted|portal_only|admin_only|material_updates|digest|all',
363
+ digestFrequency: 'daily|weekly|monthly',
326
364
  };
327
365
 
328
366
  function helpFlag(commandKey, field) {
@@ -356,6 +394,11 @@ function helpQueryFlag(field) {
356
394
  // ── Output Formatting ───────────────────────────────────────────
357
395
 
358
396
  function formatOutput(data, commandKey) {
397
+ if (commandKey === 'ops-health' && OUTPUT_JSON) {
398
+ console.log(COMPACT_JSON ? JSON.stringify(data) : JSON.stringify(data, null, 2));
399
+ if (data.status === 'critical') exitGracefully(1);
400
+ return;
401
+ }
359
402
  if (OUTPUT_JSON) {
360
403
  console.log(COMPACT_JSON ? JSON.stringify(data) : JSON.stringify(data, null, 2));
361
404
  return;
@@ -422,6 +465,111 @@ function formatOutput(data, commandKey) {
422
465
  return;
423
466
  }
424
467
 
468
+ if (commandKey === 'inbox') {
469
+ const sections = data.sections || {};
470
+ console.log('\nOperator Inbox');
471
+ console.log('-'.repeat(80));
472
+ for (const [key, section] of Object.entries(sections)) {
473
+ const items = section.items || [];
474
+ if (items.length === 0) continue;
475
+ console.log(`\n${key} (${items.length})`);
476
+ for (const item of items) {
477
+ const unread = item.unread ? '*' : ' ';
478
+ const scope = [item.clientName, item.projectName].filter(Boolean).join(' / ');
479
+ console.log(` ${unread} ${item.summary} ${scope ? `- ${scope}` : ''} [${item.id}]`);
480
+ }
481
+ }
482
+ return;
483
+ }
484
+
485
+ if (commandKey === 'reports.monthly') {
486
+ const report = data.report;
487
+ if (!report) { console.log(JSON.stringify(data, null, 2)); return; }
488
+ if (COMPACT_JSON) {
489
+ console.log(`${report.client.name}: ${report.period} - ${report.completedWork.length} done, ${report.openWork.length} open`);
490
+ return;
491
+ }
492
+ console.log(`\nMonthly Report: ${report.client.name} (${report.period})`);
493
+ console.log('-'.repeat(80));
494
+ console.log(`Completed work: ${report.completedWork.length}`);
495
+ for (const item of report.completedWork) console.log(` - ${item.title}`);
496
+ console.log(`Open work: ${report.openWork.length}`);
497
+ for (const item of report.openWork) console.log(` - ${item.title} [${item.status}]`);
498
+ console.log(`Updates: ${report.updates.length}`);
499
+ console.log(`Invoices: ${report.invoices.length}`);
500
+ console.log(`Capacity items: ${report.capacity.length}`);
501
+ return;
502
+ }
503
+
504
+ if (commandKey === 'client.timeline' || commandKey === 'project.timeline') {
505
+ const items = data.data || [];
506
+ if (items.length === 0) { console.log('No timeline events found.'); return; }
507
+ console.log(`\nTimeline (${items.length})`);
508
+ console.log('-'.repeat(80));
509
+ for (const item of items) {
510
+ const scope = [item.clientName, item.projectName].filter(Boolean).join(' / ');
511
+ console.log(` ${item.type}: ${item.summary}${scope ? ` - ${scope}` : ''} [${item.sourceId}]`);
512
+ }
513
+ return;
514
+ }
515
+
516
+ if (commandKey === 'ops-health') {
517
+ console.log(`Operational health: ${data.status}`);
518
+ for (const [key, value] of Object.entries(data.failures || {})) {
519
+ console.log(` ${key}: ${value}`);
520
+ }
521
+ if (data.status === 'critical') exitGracefully(1);
522
+ return;
523
+ }
524
+
525
+ if (commandKey === 'smoke.notifications') {
526
+ const smoke = data.smoke || {};
527
+ console.log(`Notification smoke: ${smoke.client?.name || 'client'}`);
528
+ console.log(` Read-only dry run: ${smoke.dryRun === false ? 'false' : 'true'}`);
529
+ console.log(` notificationsEnabled: ${smoke.client?.notificationsEnabled}`);
530
+ console.log(` preference: ${smoke.preference?.mode || 'n/a'}`);
531
+ console.log(` failed deliveries: ${smoke.failedCount ?? 0}`);
532
+ console.log(' Would send: none');
533
+ console.log(' Would create: none');
534
+ return;
535
+ }
536
+
537
+ if (
538
+ commandKey === 'clients.notifications.get' ||
539
+ commandKey === 'clients.notifications.update' ||
540
+ commandKey === 'projects.notifications.get' ||
541
+ commandKey === 'projects.notifications.update'
542
+ ) {
543
+ const preference = data.preference || {};
544
+ console.log(`Notification preference: ${preference.mode || 'n/a'}`);
545
+ if (preference.digestFrequency) console.log(` Digest: ${preference.digestFrequency}`);
546
+ if (preference.inheritedFromClient) console.log(' Inherited from client preference.');
547
+ if (preference.inheritedFromNotificationsEnabled) console.log(' Inherited from notificationsEnabled.');
548
+ return;
549
+ }
550
+
551
+ if (commandKey === 'notifications.preview') {
552
+ const preview = data.preview || {};
553
+ console.log(`Notification preview: ${preview.subject || preview.eventType}`);
554
+ console.log(` Audience: ${(preview.audience || []).join(', ') || 'none'}`);
555
+ console.log(` Mode: ${preview.mode || 'n/a'}`);
556
+ console.log(` Thread: ${preview.threadKey || 'n/a'}`);
557
+ console.log('');
558
+ console.log(preview.body || '');
559
+ return;
560
+ }
561
+
562
+ if (commandKey === 'audit.list' || commandKey === 'audit.target') {
563
+ const items = data.data || [];
564
+ if (items.length === 0) { console.log('No audit events found.'); return; }
565
+ console.log(`\nAudit Events (${items.length})`);
566
+ console.log('-'.repeat(80));
567
+ for (const item of items) {
568
+ console.log(` ${item.action}: ${item.targetType}/${item.targetId} [${item.id}]`);
569
+ }
570
+ return;
571
+ }
572
+
425
573
  if (commandKey === 'projects.get') {
426
574
  const p = data.project;
427
575
  console.log(`\n${p.name} [${p.status}]`);
@@ -778,6 +926,11 @@ if (!resource || resource === 'help' || resource === '--help') {
778
926
  }
779
927
  console.log(`\nConfig: PORTAL_API_URL, PORTAL_API_KEY, PORTAL_TOKEN (or ~/.klevar/portal.env)`);
780
928
  console.log(`Target: ${BASE_URL}`);
929
+ console.log('\nExamples:');
930
+ console.log(' klevar-portal inbox --unread --compact');
931
+ console.log(' klevar-portal client timeline "Acme Ltd" --type task');
932
+ console.log(' klevar-portal notifications preview project.status_changed --client "Acme Ltd" --project "Retainer"');
933
+ console.log(' klevar-portal audit target task <taskId>');
781
934
  exitGracefully(0);
782
935
  }
783
936
 
@@ -827,19 +980,25 @@ if (supportsCommentContentInput(commandKey)) {
827
980
  }
828
981
  }
829
982
 
983
+ if (commandKey === 'audit.target' && positional.length >= 2) {
984
+ flags.targetType = positional[0];
985
+ flags.targetId = positional[1];
986
+ }
987
+
830
988
  // Interpolate path
831
989
  let path = cmd.path;
832
990
  const pathParams = [...path.matchAll(/:([A-Za-z][A-Za-z0-9_]*)/g)].map((match) => match[1]);
833
991
  if (pathParams.length > 0) {
834
- pathParams.forEach((paramName, index) => {
835
- const value = positional[index];
992
+ for (const [index, paramName] of pathParams.entries()) {
993
+ let value = positional[index];
836
994
  if (!value) {
837
995
  const ordinal = index === 0 ? 'an ID argument' : `argument ${index + 1} for :${paramName}`;
838
996
  console.error(`Command '${commandKey}' requires ${ordinal}.`);
839
997
  exitGracefully(1);
840
998
  }
999
+ value = await resolveNameParam(commandKey, paramName, value, flags);
841
1000
  path = path.replace(`:${paramName}`, value);
842
- });
1001
+ }
843
1002
  }
844
1003
 
845
1004
  // Append query parameters for GET commands with filters
@@ -858,6 +1017,11 @@ if (cmd.queryParams || cmd.fixedQuery) {
858
1017
  if (qs) path += (path.includes('?') ? '&' : '?') + qs;
859
1018
  }
860
1019
 
1020
+ if (commandKey.startsWith('smoke.') && (flags.write === 'true' || flags.send === 'true')) {
1021
+ console.error(`Command '${commandKey}' is read-only; --write/--send are not supported for this smoke check.`);
1022
+ exitGracefully(2);
1023
+ }
1024
+
861
1025
  // Build body from flags or fixedBody
862
1026
  let body = undefined;
863
1027
  if (cmd.fixedBody) {
@@ -887,6 +1051,13 @@ if (supportsCommentContentInput(commandKey) && !body && positional[pathParams.le
887
1051
  body = { content: normalizeCliMultiline(positional.slice(pathParams.length).join(' ')) };
888
1052
  }
889
1053
 
1054
+ if (flags['dry-run'] === 'true' && ['POST', 'PATCH', 'DELETE'].includes(cmd.method)) {
1055
+ console.log(`Dry run: ${cmd.method} ${path}`);
1056
+ if (body) console.log(COMPACT_JSON ? JSON.stringify(body) : JSON.stringify(body, null, 2));
1057
+ else console.log('No request body.');
1058
+ exitGracefully(0);
1059
+ }
1060
+
890
1061
  // ── Search Command ──
891
1062
  if (commandKey === 'search') {
892
1063
  const q = [id, ...positional.slice(1)].filter(Boolean).join(' ');
@@ -894,8 +1065,13 @@ if (commandKey === 'search') {
894
1065
  console.error('Usage: search <term>');
895
1066
  exitGracefully(1);
896
1067
  }
897
- const data = await api('GET', `/api/admin/search?q=${encodeURIComponent(q)}`);
898
- const hasResults = data.projects.length + data.tasks.length + data.updates.length > 0;
1068
+ const params = new URLSearchParams({ q });
1069
+ for (const key of ['client', 'clientId', 'project', 'projectId', 'type', 'limit']) {
1070
+ if (flags[key] !== undefined) params.set(key, flags[key]);
1071
+ }
1072
+ const data = await api('GET', `/api/admin/search?${params.toString()}`);
1073
+ const resultGroups = ['clients', 'projects', 'tasks', 'updates', 'comments', 'notes', 'docs', 'capacity'];
1074
+ const hasResults = resultGroups.some((group) => (data[group] || []).length > 0);
899
1075
 
900
1076
  if (!hasResults) {
901
1077
  console.log(`No results for "${q}"`);
@@ -905,7 +1081,15 @@ if (commandKey === 'search') {
905
1081
  console.log(`\nSearch: "${q}"`);
906
1082
  console.log('─'.repeat(50));
907
1083
 
908
- if (data.projects.length > 0) {
1084
+ if (data.clients?.length > 0) {
1085
+ console.log('\nClients:');
1086
+ data.clients.forEach((c) => {
1087
+ const company = c.company ? ` (${c.company})` : '';
1088
+ console.log(` • ${c.name}${company} [${c.status}] [${c.id}]`);
1089
+ });
1090
+ }
1091
+
1092
+ if ((data.projects || []).length > 0) {
909
1093
  console.log('\nProjects:');
910
1094
  data.projects.forEach((p) => {
911
1095
  const visibility = p.visibility ? ` [${p.visibility}]` : '';
@@ -915,7 +1099,7 @@ if (commandKey === 'search') {
915
1099
  console.log('\nProjects: (none)');
916
1100
  }
917
1101
 
918
- if (data.tasks.length > 0) {
1102
+ if ((data.tasks || []).length > 0) {
919
1103
  console.log('\nTasks:');
920
1104
  data.tasks.forEach((t) => {
921
1105
  const prio = t.priority && t.priority !== 'normal' ? ` (${t.priority})` : '';
@@ -925,7 +1109,7 @@ if (commandKey === 'search') {
925
1109
  console.log('\nTasks: (none)');
926
1110
  }
927
1111
 
928
- if (data.updates.length > 0) {
1112
+ if ((data.updates || []).length > 0) {
929
1113
  console.log('\nUpdates:');
930
1114
  data.updates.forEach((u) => {
931
1115
  const vis = u.visibility === 'internal' ? ' [INTERNAL]' : '';
@@ -935,6 +1119,16 @@ if (commandKey === 'search') {
935
1119
  console.log('\nUpdates: (none)');
936
1120
  }
937
1121
 
1122
+ for (const [label, key] of [['Comments', 'comments'], ['Notes', 'notes'], ['Docs', 'docs'], ['Capacity', 'capacity']]) {
1123
+ const items = data[key] || [];
1124
+ if (items.length === 0) continue;
1125
+ console.log(`\n${label}:`);
1126
+ items.forEach((item) => {
1127
+ const text = item.title || item.contentPreview || item.documentNumber || item.documentType || item.status || item.billableStatus || item.id;
1128
+ console.log(` • ${text} [${item.id}]`);
1129
+ });
1130
+ }
1131
+
938
1132
  exitGracefully(0);
939
1133
  }
940
1134
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klevar/portal-cli",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "First-class npm CLI for the Klevar Client Management Portal",
5
5
  "type": "module",
6
6
  "bin": {