quoxcli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/README.md +2 -2
- package/bin/quox.js +19 -1
- package/bin/quoxon.js +6 -1
- package/lib/api/endpoints/admin.js +7 -0
- package/lib/api/endpoints/agent-attach.js +7 -0
- package/lib/api/endpoints/compliance.js +25 -0
- package/lib/api/endpoints/inbox.js +6 -0
- package/lib/api/endpoints/inboxq.js +19 -0
- package/lib/api/endpoints/index.js +2 -0
- package/lib/api/endpoints/mon.js +122 -0
- package/lib/api/endpoints/tools.js +13 -0
- package/lib/api/endpoints/v1.js +13 -0
- package/lib/commands/admin.js +35 -0
- package/lib/commands/agentAttach.js +15 -0
- package/lib/commands/approvals.js +193 -3
- package/lib/commands/ask.js +1 -1
- package/lib/commands/auth.js +64 -11
- package/lib/commands/backup.js +11 -4
- package/lib/commands/capabilities.js +3 -2
- package/lib/commands/chat.js +15 -0
- package/lib/commands/claude.js +4 -1
- package/lib/commands/compliance.js +109 -0
- package/lib/commands/connect.js +69 -0
- package/lib/commands/dev.js +6 -8
- package/lib/commands/doctor.js +22 -3
- package/lib/commands/evidence.js +2 -1
- package/lib/commands/gripe.js +24 -13
- package/lib/commands/inbox.js +37 -3
- package/lib/commands/inboxq.js +147 -0
- package/lib/commands/kuma.js +78 -5
- package/lib/commands/licenceLinkView.js +311 -0
- package/lib/commands/linkedin.js +19 -0
- package/lib/commands/loop.js +30 -3
- package/lib/commands/lucid.js +1 -0
- package/lib/commands/mail.js +161 -20
- package/lib/commands/memory.js +68 -4
- package/lib/commands/memorySync.js +158 -0
- package/lib/commands/mon.js +55 -144
- package/lib/commands/notes.js +29 -7
- package/lib/commands/notesSeal.js +259 -0
- package/lib/commands/objective.js +5 -2
- package/lib/commands/offload.js +2 -3
- package/lib/commands/plan.js +17 -0
- package/lib/commands/provider.js +29 -8
- package/lib/commands/qlarity.js +32 -1
- package/lib/commands/run.js +2 -1
- package/lib/commands/server.js +37 -0
- package/lib/commands/setup.js +127 -75
- package/lib/commands/skills.js +4 -1
- package/lib/commands/slot.js +49 -9
- package/lib/commands/status.js +92 -44
- package/lib/commands/tool.js +30 -0
- package/lib/commands/vault.js +6 -3
- package/lib/commands/walkthrough.js +14 -2
- package/lib/commands/watch.js +11 -2
- package/lib/commands/wazuh.js +824 -0
- package/lib/commands/wazuhIntake.js +317 -0
- package/lib/commands/wazuhReport.js +192 -0
- package/lib/commands/workflow.js +47 -4
- package/lib/commands/x.js +50 -0
- package/lib/core/announce.js +86 -0
- package/lib/core/auth.js +20 -2
- package/lib/core/callMe.js +118 -0
- package/lib/core/client.js +27 -1
- package/lib/core/commandRegistrars.js +8 -0
- package/lib/core/config.js +28 -2
- package/lib/core/confirm.js +68 -7
- package/lib/core/crossOrgApprovals.js +69 -0
- package/lib/core/errors.js +52 -1
- package/lib/core/governedSession.js +135 -5
- package/lib/core/inboxResolution.js +3 -2
- package/lib/core/loginGuard.js +73 -0
- package/lib/core/offload.js +37 -0
- package/lib/core/org-override.js +5 -1
- package/lib/core/output.js +1 -1
- package/lib/core/profileTrust.js +182 -0
- package/lib/core/quoxglyph.js +22 -1
- package/lib/core/router.js +14 -0
- package/lib/core/stepUpPrompt.js +99 -0
- package/lib/core/version.js +1 -1
- package/lib/core/walkthrough.js +9 -5
- package/lib/dragon/select.js +2 -2
- package/lib/quoxon/EXTENSIONS.md +142 -19
- package/lib/quoxon/api.js +185 -34
- package/lib/quoxon/app.js +1032 -152
- package/lib/quoxon/approvalBatch.js +117 -0
- package/lib/quoxon/approvalFacts.js +56 -2
- package/lib/quoxon/approvalSentence.js +8 -4
- package/lib/quoxon/approvalsView.js +69 -11
- package/lib/quoxon/autoOpen.js +94 -0
- package/lib/quoxon/backgroundWork.js +59 -0
- package/lib/quoxon/bang.js +1 -1
- package/lib/quoxon/capabilities.js +7 -2
- package/lib/quoxon/commandShort.js +7 -0
- package/lib/quoxon/commands.js +40 -10
- package/lib/quoxon/connect.js +5 -3
- package/lib/quoxon/deckLazy.js +58 -0
- package/lib/quoxon/destructive.js +35 -0
- package/lib/quoxon/dnd.js +71 -0
- package/lib/quoxon/dragonCompanion.js +37 -7
- package/lib/quoxon/dragonMoments.js +78 -0
- package/lib/quoxon/echo.js +1 -0
- package/lib/quoxon/events.js +43 -7
- package/lib/quoxon/extensions.js +398 -38
- package/lib/quoxon/gripeQueue.js +135 -0
- package/lib/quoxon/inboxView.js +125 -22
- package/lib/quoxon/keys.js +2 -2
- package/lib/quoxon/loopCard.js +5 -1
- package/lib/quoxon/loopCards.js +17 -8
- package/lib/quoxon/loopStream.js +20 -9
- package/lib/quoxon/mailView.js +71 -0
- package/lib/quoxon/main.js +20 -5
- package/lib/quoxon/markdown.js +1 -1
- package/lib/quoxon/model.js +15 -0
- package/lib/quoxon/neverAnswered.js +20 -0
- package/lib/quoxon/objects/away.js +43 -5
- package/lib/quoxon/onboarding/connectServer.js +162 -0
- package/lib/quoxon/onboarding/copy.js +6 -0
- package/lib/quoxon/onboarding/index.js +5 -43
- package/lib/quoxon/onboarding/probe.js +20 -1
- package/lib/quoxon/onboarding/view.js +16 -3
- package/lib/quoxon/orgSwitch.js +22 -0
- package/lib/quoxon/print.js +2 -0
- package/lib/quoxon/profileSwitch.js +7 -0
- package/lib/quoxon/promptHistory.js +3 -1
- package/lib/quoxon/render.js +63 -14
- package/lib/quoxon/roster.js +10 -5
- package/lib/quoxon/rosterSessions.js +44 -0
- package/lib/quoxon/screenContext.js +1 -1
- package/lib/quoxon/secretShape.js +86 -0
- package/lib/quoxon/slash/agents.js +2 -1
- package/lib/quoxon/slash/argSources.js +9 -2
- package/lib/quoxon/slash/args.js +4 -2
- package/lib/quoxon/slash/broadcast.js +18 -5
- package/lib/quoxon/slash/broadcastRun.js +13 -2
- package/lib/quoxon/slash/cliLeaves.json +63 -1
- package/lib/quoxon/slash/hatWalk.js +1 -1
- package/lib/quoxon/slash/palette.js +22 -1
- package/lib/quoxon/slash/paletteController.js +10 -4
- package/lib/quoxon/slash/restart.js +7 -4
- package/lib/quoxon/slash/stepUp.js +5 -5
- package/lib/quoxon/slash/stepUpCmds.js +74 -1
- package/lib/quoxon/slashSpinner.js +35 -0
- package/lib/quoxon/slotAttach.js +8 -0
- package/lib/quoxon/slotChat.js +17 -0
- package/lib/quoxon/slotFormat.js +1 -1
- package/lib/quoxon/slotOutbox.js +113 -0
- package/lib/quoxon/suggestCommand.js +1 -1
- package/lib/quoxon/term.js +25 -1
- package/lib/quoxon/transcript.js +2 -1
- package/lib/quoxon/welcome.js +1 -1
- package/lib/quoxon/whatsnew.js +1 -1
- package/lib/quoxon/whatsnew.jsonl +36 -0
- package/lib/server/installFlow.js +168 -0
- package/lib/server/status.js +15 -1
- package/lib/toolOutputShape.js +55 -0
- package/package.json +3 -2
- package/vendor/dragonlab/SOURCE +3 -3
- package/vendor/dragonlab/design/quoxperticus/v2/quoxperticus-master.svg +59 -0
- package/vendor/dragonlab/design/quoxperticus/v3/character.mjs +43 -0
- package/vendor/dragonlab/design/quoxperticus/v4/character.mjs +57 -0
- package/vendor/dragonlab/design/quoxperticus/v4/review.mjs +35 -0
- package/vendor/dragonlab/design/quoxperticus/v4/watch.mjs +56 -0
- package/vendor/dragonlab/design/vulcan/v1/character.mjs +34 -0
- package/vendor/dragonlab/design/vulcan/v1/vulcan-master.svg +57 -0
- package/vendor/dragonlab/design/vulcan/v2/character.mjs +39 -0
- package/vendor/dragonlab/design/vulcan/v3/character.mjs +41 -0
- package/vendor/dragonlab/design/vulcan/v3/review.mjs +35 -0
- package/vendor/dragonlab/design/vulcan/v3/watch.mjs +56 -0
- package/vendor/dragonlab/factory/svg-rig-contour.mjs +64 -0
- package/vendor/dragonlab/integration/companions-v1/characters.mjs +20 -0
- package/vendor/dragonlab/integration/companions-v1/quoxperticus.mjs +2 -0
- package/vendor/dragonlab/integration/companions-v1/view.mjs +1 -1
- package/vendor/dragonlab/integration/companions-v1/vulcan.mjs +2 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
User-visible changes to the `quoxcli` package. Items marked *(unproven)* ship in
|
|
4
|
+
the package and pass their tests, but nobody has run them end to end from the
|
|
5
|
+
published package yet.
|
|
6
|
+
|
|
7
|
+
## 0.5.0 (unreleased)
|
|
8
|
+
|
|
9
|
+
### New commands
|
|
10
|
+
- `quox wazuh`: first-class Wazuh commands. `agents`, `fim`, `sca`, `rootcheck`
|
|
11
|
+
and `coverage` are reads. `vulns --priority` ranks CVEs by CISA KEV, EPSS,
|
|
12
|
+
CVSS and how many hosts each one hits (driven live across the fleet before
|
|
13
|
+
this release). Fleet-wide reads cover up to 200 active agents (it was a
|
|
14
|
+
silent 25 before).
|
|
15
|
+
- `quox wazuh report generate | list | show | verify`: signed vulnerability
|
|
16
|
+
reports. `verify` works offline against a pinned PEM or a raw key.
|
|
17
|
+
*(unproven from the package)*
|
|
18
|
+
- `quox wazuh connect`, `quox wazuh hooks create | list | rotate | delete | install`,
|
|
19
|
+
`quox wazuh incidents [--open] [--since] | show | close | diagnose | escalate`
|
|
20
|
+
and `quox wazuh triage`. Writes go through one approval per call.
|
|
21
|
+
*(unproven from the package)*
|
|
22
|
+
- `quox compliance reports list | show` (read): framework, period, score,
|
|
23
|
+
status per control and sampled evidence ids. `quox compliance jobs list`, and
|
|
24
|
+
jobs can now be named. *(unproven from the package)*
|
|
25
|
+
- `quox tool installed` and `quox tool uninstall`, to read back and undo a
|
|
26
|
+
`quox tool install`. *(unproven from the package)*
|
|
27
|
+
- `quox approvals approve | deny | list` by id or short tail, `quox approvals withdraw`
|
|
28
|
+
(the requester takes its own hold back), and `quox approvals call-me [status|on|off]`
|
|
29
|
+
(needs the quox-voice licence).
|
|
30
|
+
- `quox connect <url>` with certificate pinning per profile (`--trust-cert`,
|
|
31
|
+
`--fingerprint`), and `quox server install` (with `--dry-run`, `--yes`, `--json`).
|
|
32
|
+
- `quox notes seal init | status | new | open | edit | print`: ENQRYPT sealed
|
|
33
|
+
notes. Encryption happens on your machine and the server stores only the
|
|
34
|
+
envelope. *(unproven from the package)*
|
|
35
|
+
- `quox admin users verify-email <email> --reason` (step-up PIN).
|
|
36
|
+
- `quox memory sync`: Claude file memory is saved to Quox memory too
|
|
37
|
+
(idempotent; credential-shaped text is refused).
|
|
38
|
+
- `quox inbox unread <id...>`, `quox x whoami | accounts`, `quox linkedin whoami`,
|
|
39
|
+
`quox workflow create | apply | import-n8n --activate` (a plain create is not armed).
|
|
40
|
+
|
|
41
|
+
### Terminal UI (quoxon)
|
|
42
|
+
- New approvals and questions open by themselves as the walkthrough card.
|
|
43
|
+
- Approve verbs ask for the step-up PIN on a terminal; destructive approvals
|
|
44
|
+
need the target name typed.
|
|
45
|
+
- Do not disturb and `/sleep` survive restarts; `/morningreport` gives a grouped
|
|
46
|
+
digest of what arrived while you were away.
|
|
47
|
+
- `/mail` reads triaged email (read-only), `/outbox` queues `/say` sends that
|
|
48
|
+
failed on connectivity and sends them in order once you are back online.
|
|
49
|
+
- Other-org approvals show on the bar, with a hint about how many more are waiting.
|
|
50
|
+
- A secret paste guard asks before it sends text that looks like a credential,
|
|
51
|
+
and redacts it from history.
|
|
52
|
+
- Extensions hot-reload, and extension host contract v1 is out (panels, tabs,
|
|
53
|
+
settings).
|
|
54
|
+
|
|
55
|
+
### Fixes
|
|
56
|
+
- An explicit `-p <profile>` with no session now fails, instead of quietly
|
|
57
|
+
using the service key.
|
|
58
|
+
- `quox workflow update` finds engine workflows. `quox run list` fills in its
|
|
59
|
+
columns again.
|
|
60
|
+
- Watch and loop streams back off and give up cleanly, instead of polling forever.
|
|
61
|
+
- Docs links point at quox.ai/cli.
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ npm install -g quoxcli
|
|
|
12
12
|
|
|
13
13
|
Needs Node.js 20 or later. This installs two commands: `quox`, and `quoxon` (an alias that opens the conversation).
|
|
14
14
|
|
|
15
|
-
Docs: https://
|
|
15
|
+
Docs: https://quox.ai/cli/docs/quickstart/
|
|
16
16
|
|
|
17
17
|
## Prerequisite: a running QuoxCORE
|
|
18
18
|
|
|
@@ -142,4 +142,4 @@ export NODE_EXTRA_CA_CERTS=/path/to/your-ca.pem
|
|
|
142
142
|
Quox Community Source Licence 1.0. This is source-available software, not open source. You may self-host and inspect it freely; redistribution and repackaging are restricted. Read the full text in the `LICENSE` file or at https://github.com/quoxai/quoxcore.
|
|
143
143
|
|
|
144
144
|
Website: https://quox.ai
|
|
145
|
-
CLI home: https://
|
|
145
|
+
CLI home: https://quox.ai/cli
|
package/bin/quox.js
CHANGED
|
@@ -11,6 +11,14 @@ if (!process.env.QUOX_SESSION_ID && process.env.QUOX_SESSION_ID_FILE) {
|
|
|
11
11
|
try { process.env.QUOX_SESSION_ID = (await import('node:fs')).readFileSync(process.env.QUOX_SESSION_ID_FILE, 'utf8').trim(); } catch { /* turn ended: no session */ }
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// ONBOARD-P1: a profile that trusts its server's own certificate (quox connect) makes this run trust it too, via a
|
|
15
|
+
// one-time re-run with NODE_EXTRA_CA_CERTS set for this process tree only. Before anything else loads.
|
|
16
|
+
{
|
|
17
|
+
const { reexecWithProfileTrust } = await import('../lib/core/profileTrust.js');
|
|
18
|
+
const code = reexecWithProfileTrust(process.argv.slice(2), process.env);
|
|
19
|
+
if (code !== null) process.exit(code);
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
// CORTEX-BENCH: Node's fetch parses HTTP with a WebAssembly module, and V8
|
|
15
23
|
// recompiles it at the optimising tier on a background thread; Node waits for
|
|
16
24
|
// that compile before exiting, adding 350-700ms to every short command after
|
|
@@ -167,7 +175,17 @@ if (process.argv.includes('--no-color') || process.env.NO_COLOR) {
|
|
|
167
175
|
const config = loadConfig(resolveProfileFlagFromArgv(process.argv.slice(2)));
|
|
168
176
|
const auth = createAuth(config);
|
|
169
177
|
const client = createClient(config, auth);
|
|
170
|
-
|
|
178
|
+
// A client on the SAME user's token for another org the user belongs to (minted per org, window scope, never moves the
|
|
179
|
+
// profile's org). Lazy: nothing is minted unless a verb asks (approvals --org, the "more waiting in <org>" hint).
|
|
180
|
+
let _orgClients = null;
|
|
181
|
+
const clientForOrg = async (orgId) => {
|
|
182
|
+
if (!_orgClients) {
|
|
183
|
+
const { createWindowClient } = await import('../lib/quoxon/windowOrg.js');
|
|
184
|
+
_orgClients = createWindowClient({ config, auth, createClient }).clientForOrg;
|
|
185
|
+
}
|
|
186
|
+
return _orgClients(orgId);
|
|
187
|
+
};
|
|
188
|
+
const ctx = { config, auth, client, program, clientForOrg };
|
|
171
189
|
|
|
172
190
|
// Register all command groups
|
|
173
191
|
// Command groups, in registration order. CORTEX-BENCH (quox#7xx CLI startup):
|
package/bin/quoxon.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import '../lib/core/prodEnv.js'; // first: production React unless NODE_ENV is set (before anything loads React)
|
|
3
|
-
|
|
3
|
+
{
|
|
4
|
+
const { reexecWithProfileTrust } = await import('../lib/core/profileTrust.js');
|
|
5
|
+
const code = reexecWithProfileTrust(process.argv.slice(2), process.env);
|
|
6
|
+
if (code !== null) process.exit(code);
|
|
7
|
+
}
|
|
8
|
+
const { main } = await import('../lib/quoxon/main.js');
|
|
4
9
|
|
|
5
10
|
main().catch((err) => {
|
|
6
11
|
console.error(err?.message || err);
|
|
@@ -17,6 +17,13 @@ export const admin = {
|
|
|
17
17
|
path: () => '/api/admin/agent-identities',
|
|
18
18
|
tags: ['admin-write'],
|
|
19
19
|
},
|
|
20
|
+
// ADMIN-VERIFY-EMAIL: instance-admin + human + step-up (scope override). Served by services/auth/routes/admin.js.
|
|
21
|
+
'admin.users.verify_email': {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
service: 'auth',
|
|
24
|
+
path: () => '/api/admin/users/verify-email',
|
|
25
|
+
tags: ['admin-write'],
|
|
26
|
+
},
|
|
20
27
|
// Instance basics after setup (app URL etc). Served by services/auth/routes/admin-instance.js.
|
|
21
28
|
'admin.instance.basics.get': {
|
|
22
29
|
method: 'GET',
|
|
@@ -27,6 +27,13 @@ export const agentAttach = {
|
|
|
27
27
|
path: ({ leaseId }) => `/api/agent-attach/lease/${encodeURIComponent(leaseId)}/release`,
|
|
28
28
|
tags: ['live-write'],
|
|
29
29
|
},
|
|
30
|
+
// Org-wide list of live attaches (org owner/admin). Feeds `quox agent attaches` and the quoxon /roster.
|
|
31
|
+
'agent-attach.list': {
|
|
32
|
+
method: 'GET',
|
|
33
|
+
service: 'auth',
|
|
34
|
+
path: () => '/api/agent-attach',
|
|
35
|
+
tags: ['live-safe'],
|
|
36
|
+
},
|
|
30
37
|
'agent-attach.status': {
|
|
31
38
|
method: 'GET',
|
|
32
39
|
service: 'auth',
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 'compliance.*' endpoints: scheduled compliance report jobs and generated reports.
|
|
3
|
+
* See cli/lib/api/endpoints/index.js for aggregation + the fragment convention.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const compliance = {
|
|
7
|
+
'compliance.jobs.list': {
|
|
8
|
+
method: 'GET',
|
|
9
|
+
service: 'collector',
|
|
10
|
+
path: () => `/compliance/jobs`,
|
|
11
|
+
tags: ['live-safe'],
|
|
12
|
+
},
|
|
13
|
+
'compliance.reports.list': {
|
|
14
|
+
method: 'GET',
|
|
15
|
+
service: 'collector',
|
|
16
|
+
path: () => `/compliance/reports`,
|
|
17
|
+
tags: ['live-safe'],
|
|
18
|
+
},
|
|
19
|
+
'compliance.reports.get': {
|
|
20
|
+
method: 'GET',
|
|
21
|
+
service: 'collector',
|
|
22
|
+
path: ({ id }) => `/compliance/reports/${encodeURIComponent(id)}`,
|
|
23
|
+
tags: ['live-safe'],
|
|
24
|
+
},
|
|
25
|
+
};
|
|
@@ -30,6 +30,12 @@ export const inbox = {
|
|
|
30
30
|
path: ({ orgId, itemId }) => `/api/orgs/${orgId}/inbox/${itemId}/respond`,
|
|
31
31
|
tags: ['live-write'],
|
|
32
32
|
},
|
|
33
|
+
'inbox.withdraw': {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
service: 'auth',
|
|
36
|
+
path: ({ orgId, itemId }) => `/api/orgs/${orgId}/inbox/${itemId}/withdraw`,
|
|
37
|
+
tags: ['live-write'],
|
|
38
|
+
},
|
|
33
39
|
// quox ask: a session files a decision request (one inbox item) and waits for the human's answer.
|
|
34
40
|
'inbox.decision.create': {
|
|
35
41
|
method: 'POST',
|
|
@@ -26,6 +26,19 @@ export const inboxq = {
|
|
|
26
26
|
path: ({ accountId }) => `/api/v1/inboxq/accounts/${accountId}`,
|
|
27
27
|
tags: ['live-write'],
|
|
28
28
|
},
|
|
29
|
+
// quox#1504: per-account TLS certificate pin (human org admin only).
|
|
30
|
+
'inboxq.accounts.tlsPin': {
|
|
31
|
+
method: 'PUT',
|
|
32
|
+
service: 'collector',
|
|
33
|
+
path: ({ accountId }) => `/api/v1/inboxq/accounts/${encodeURIComponent(accountId)}/tls-pin`,
|
|
34
|
+
tags: ['live-write'],
|
|
35
|
+
},
|
|
36
|
+
'inboxq.syncStatus': {
|
|
37
|
+
method: 'GET',
|
|
38
|
+
service: 'collector',
|
|
39
|
+
path: () => `/api/v1/inboxq/sync-status`,
|
|
40
|
+
tags: ['live-safe'],
|
|
41
|
+
},
|
|
29
42
|
'inboxq.messages.get': {
|
|
30
43
|
method: 'GET',
|
|
31
44
|
service: 'collector',
|
|
@@ -99,6 +112,12 @@ export const inboxq = {
|
|
|
99
112
|
path: ({ watchId }) => `/api/v1/inboxq/watches/${watchId}/active`,
|
|
100
113
|
tags: ['live-write'],
|
|
101
114
|
},
|
|
115
|
+
'inboxq.watches.delete': {
|
|
116
|
+
method: 'DELETE',
|
|
117
|
+
service: 'collector',
|
|
118
|
+
path: ({ watchId }) => `/api/v1/inboxq/watches/${watchId}`,
|
|
119
|
+
tags: ['live-write'],
|
|
120
|
+
},
|
|
102
121
|
'inboxq.proposals.list': {
|
|
103
122
|
method: 'GET',
|
|
104
123
|
service: 'collector',
|
|
@@ -74,6 +74,7 @@ import { budgets } from './budgets.js';
|
|
|
74
74
|
import { calendarq } from './calendarq.js';
|
|
75
75
|
import { catalog } from './catalog.js';
|
|
76
76
|
import { chat } from './chat.js';
|
|
77
|
+
import { compliance } from './compliance.js';
|
|
77
78
|
import { consent } from './consent.js';
|
|
78
79
|
import { conversations } from './conversations.js';
|
|
79
80
|
import { customRoles } from './custom-roles.js';
|
|
@@ -166,6 +167,7 @@ export const ENDPOINTS = {
|
|
|
166
167
|
...calendarq,
|
|
167
168
|
...catalog,
|
|
168
169
|
...chat,
|
|
170
|
+
...compliance,
|
|
169
171
|
...consent,
|
|
170
172
|
...conversations,
|
|
171
173
|
...customRoles,
|
package/lib/api/endpoints/mon.js
CHANGED
|
@@ -163,6 +163,12 @@ export const mon = {
|
|
|
163
163
|
path: ({ id } = {}) => `/api/v1/kuma/monitors/${encodeURIComponent(id)}/resume`,
|
|
164
164
|
tags: ['live-write'],
|
|
165
165
|
},
|
|
166
|
+
'mon.kuma.monitors.wire-alerts': {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
service: 'collector',
|
|
169
|
+
path: ({ id } = {}) => `/api/v1/kuma/monitors/${encodeURIComponent(id)}/wire-alerts`,
|
|
170
|
+
tags: ['live-write'],
|
|
171
|
+
},
|
|
166
172
|
'mon.kuma.monitors.delete': {
|
|
167
173
|
method: 'DELETE',
|
|
168
174
|
service: 'collector',
|
|
@@ -318,12 +324,36 @@ export const mon = {
|
|
|
318
324
|
path: () => `/api/v1/wazuh/agents`,
|
|
319
325
|
tags: ['live-safe'],
|
|
320
326
|
},
|
|
327
|
+
'mon.wazuh.read': {
|
|
328
|
+
method: 'GET',
|
|
329
|
+
service: 'collector',
|
|
330
|
+
path: ({ tool }) => `/api/v1/wazuh/read/${tool}`,
|
|
331
|
+
tags: ['live-safe'],
|
|
332
|
+
},
|
|
321
333
|
'mon.wazuh.alerts.list': {
|
|
322
334
|
method: 'GET',
|
|
323
335
|
service: 'collector',
|
|
324
336
|
path: () => `/api/v1/wazuh/alerts`,
|
|
325
337
|
tags: ['live-safe'],
|
|
326
338
|
},
|
|
339
|
+
'mon.wazuh.alerts.triage': {
|
|
340
|
+
method: 'GET',
|
|
341
|
+
service: 'collector',
|
|
342
|
+
path: () => `/api/v1/wazuh/alerts/triage`,
|
|
343
|
+
tags: ['live-safe'],
|
|
344
|
+
},
|
|
345
|
+
'mon.wazuh.coverage': {
|
|
346
|
+
method: 'GET',
|
|
347
|
+
service: 'collector',
|
|
348
|
+
path: () => `/api/v1/wazuh/coverage`,
|
|
349
|
+
tags: ['live-safe'],
|
|
350
|
+
},
|
|
351
|
+
'mon.wazuh.credential.import-instance-env': {
|
|
352
|
+
method: 'POST',
|
|
353
|
+
service: 'collector',
|
|
354
|
+
path: () => `/api/v1/wazuh/credential/import-instance-env`,
|
|
355
|
+
tags: ['live-write'],
|
|
356
|
+
},
|
|
327
357
|
'mon.wazuh.deploy-agent': {
|
|
328
358
|
method: 'POST',
|
|
329
359
|
service: 'collector',
|
|
@@ -348,6 +378,98 @@ export const mon = {
|
|
|
348
378
|
path: () => `/api/v1/wazuh/manager/status`,
|
|
349
379
|
tags: ['live-safe'],
|
|
350
380
|
},
|
|
381
|
+
'mon.wazuh.reports.create': {
|
|
382
|
+
method: 'POST',
|
|
383
|
+
service: 'collector',
|
|
384
|
+
path: () => `/api/v1/wazuh/reports`,
|
|
385
|
+
tags: ['live-safe'],
|
|
386
|
+
},
|
|
387
|
+
'mon.wazuh.reports.list': {
|
|
388
|
+
method: 'GET',
|
|
389
|
+
service: 'collector',
|
|
390
|
+
path: () => `/api/v1/wazuh/reports`,
|
|
391
|
+
tags: ['live-safe'],
|
|
392
|
+
},
|
|
393
|
+
'mon.wazuh.reports.get': {
|
|
394
|
+
method: 'GET',
|
|
395
|
+
service: 'collector',
|
|
396
|
+
path: ({ id } = {}) => `/api/v1/wazuh/reports/${encodeURIComponent(id)}`,
|
|
397
|
+
tags: ['live-safe'],
|
|
398
|
+
},
|
|
399
|
+
'mon.wazuh.reports.verify': {
|
|
400
|
+
method: 'GET',
|
|
401
|
+
service: 'collector',
|
|
402
|
+
path: ({ id } = {}) => `/api/v1/wazuh/reports/${encodeURIComponent(id)}/verify`,
|
|
403
|
+
tags: ['live-safe'],
|
|
404
|
+
},
|
|
405
|
+
// WAZ P6: Wazuh integratord alert hooks (org admin) and the incidents they open.
|
|
406
|
+
'mon.wazuh.hooks.list': {
|
|
407
|
+
method: 'GET',
|
|
408
|
+
service: 'collector',
|
|
409
|
+
path: () => `/api/v1/wazuh/hooks`,
|
|
410
|
+
tags: ['live-safe'],
|
|
411
|
+
},
|
|
412
|
+
'mon.wazuh.hooks.create': {
|
|
413
|
+
method: 'POST',
|
|
414
|
+
service: 'collector',
|
|
415
|
+
path: () => `/api/v1/wazuh/hooks`,
|
|
416
|
+
tags: ['live-write'],
|
|
417
|
+
},
|
|
418
|
+
'mon.wazuh.hooks.rotate': {
|
|
419
|
+
method: 'POST',
|
|
420
|
+
service: 'collector',
|
|
421
|
+
path: ({ id } = {}) => `/api/v1/wazuh/hooks/${encodeURIComponent(id)}/rotate`,
|
|
422
|
+
tags: ['live-write'],
|
|
423
|
+
},
|
|
424
|
+
'mon.wazuh.hooks.delete': {
|
|
425
|
+
method: 'DELETE',
|
|
426
|
+
service: 'collector',
|
|
427
|
+
path: ({ id } = {}) => `/api/v1/wazuh/hooks/${encodeURIComponent(id)}`,
|
|
428
|
+
tags: ['live-write'],
|
|
429
|
+
},
|
|
430
|
+
'mon.wazuh.incidents.list': {
|
|
431
|
+
method: 'GET',
|
|
432
|
+
service: 'collector',
|
|
433
|
+
path: ({ open, since, limit } = {}) => {
|
|
434
|
+
const q = [];
|
|
435
|
+
if (open) q.push('open=1');
|
|
436
|
+
if (since) q.push(`since=${encodeURIComponent(since)}`);
|
|
437
|
+
if (limit) q.push(`limit=${encodeURIComponent(limit)}`);
|
|
438
|
+
return `/api/v1/wazuh/incidents${q.length ? `?${q.join('&')}` : ''}`;
|
|
439
|
+
},
|
|
440
|
+
tags: ['live-safe'],
|
|
441
|
+
},
|
|
442
|
+
'mon.wazuh.incidents.get': {
|
|
443
|
+
method: 'GET',
|
|
444
|
+
service: 'collector',
|
|
445
|
+
path: ({ id } = {}) => `/api/v1/wazuh/incidents/${encodeURIComponent(id)}`,
|
|
446
|
+
tags: ['live-safe'],
|
|
447
|
+
},
|
|
448
|
+
'mon.wazuh.incidents.close': {
|
|
449
|
+
method: 'POST',
|
|
450
|
+
service: 'collector',
|
|
451
|
+
path: ({ id } = {}) => `/api/v1/wazuh/incidents/${encodeURIComponent(id)}/close`,
|
|
452
|
+
tags: ['live-write'],
|
|
453
|
+
},
|
|
454
|
+
// WAZ P7: read-only host diagnosis (off-list reads are held by the ssh_exec approval gate) and hand-off to QuoxSecurity.
|
|
455
|
+
'mon.wazuh.incidents.diagnose': {
|
|
456
|
+
method: 'POST',
|
|
457
|
+
service: 'collector',
|
|
458
|
+
path: ({ id } = {}) => `/api/v1/wazuh/incidents/${encodeURIComponent(id)}/diagnose`,
|
|
459
|
+
tags: ['live-write'],
|
|
460
|
+
},
|
|
461
|
+
'mon.wazuh.incidents.escalate': {
|
|
462
|
+
method: 'POST',
|
|
463
|
+
service: 'collector',
|
|
464
|
+
path: ({ id } = {}) => `/api/v1/wazuh/incidents/${encodeURIComponent(id)}/escalate`,
|
|
465
|
+
tags: ['live-write'],
|
|
466
|
+
},
|
|
467
|
+
'mon.wazuh.vulnerabilities.priority': {
|
|
468
|
+
method: 'GET',
|
|
469
|
+
service: 'collector',
|
|
470
|
+
path: () => `/api/v1/wazuh/vulnerabilities/priority`,
|
|
471
|
+
tags: ['live-safe'],
|
|
472
|
+
},
|
|
351
473
|
'mon.wazuh.vulnerabilities.list': {
|
|
352
474
|
method: 'GET',
|
|
353
475
|
service: 'collector',
|
|
@@ -29,6 +29,19 @@ export const tools = {
|
|
|
29
29
|
path: () => `/api/tools/install-to-scope`,
|
|
30
30
|
tags: ['live-write'],
|
|
31
31
|
},
|
|
32
|
+
// CLI-COV 2026-11-05: read and undo what `tool install` wrote (tool_installations, not the org's tool definitions)
|
|
33
|
+
'tools.installed': {
|
|
34
|
+
method: 'GET',
|
|
35
|
+
service: 'auth',
|
|
36
|
+
path: () => `/api/tools/installed`,
|
|
37
|
+
tags: ['live-safe'],
|
|
38
|
+
},
|
|
39
|
+
'tools.uninstall-from-scope': {
|
|
40
|
+
method: 'DELETE',
|
|
41
|
+
service: 'auth',
|
|
42
|
+
path: ({ toolId }) => `/api/tools/install-to-scope/${encodeURIComponent(toolId)}`,
|
|
43
|
+
tags: ['live-write'],
|
|
44
|
+
},
|
|
32
45
|
'tools.list': {
|
|
33
46
|
method: 'GET',
|
|
34
47
|
service: 'auth',
|
package/lib/api/endpoints/v1.js
CHANGED
|
@@ -365,6 +365,19 @@ export const v1 = {
|
|
|
365
365
|
path: ({ id }) => `/api/v1/approvals/grants/${encodeURIComponent(id)}/revoke`,
|
|
366
366
|
tags: ['live-write'],
|
|
367
367
|
},
|
|
368
|
+
// ApprovalsQ call-me policy (2026-11-03): human org admin only; flips the stale-approval phone watcher.
|
|
369
|
+
'v1.approvals.call-me.get': {
|
|
370
|
+
method: 'GET',
|
|
371
|
+
service: 'collector',
|
|
372
|
+
path: () => `/api/v1/approvalsq/call-me`,
|
|
373
|
+
tags: ['live-safe'],
|
|
374
|
+
},
|
|
375
|
+
'v1.approvals.call-me.put': {
|
|
376
|
+
method: 'PUT',
|
|
377
|
+
service: 'collector',
|
|
378
|
+
path: () => `/api/v1/approvalsq/call-me`,
|
|
379
|
+
tags: ['live-write'],
|
|
380
|
+
},
|
|
368
381
|
'v1.tools.list': {
|
|
369
382
|
method: 'GET',
|
|
370
383
|
service: 'collector',
|
package/lib/commands/admin.js
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import { formatOutput, formatDetail, printSuccess } from '../core/output.js';
|
|
6
6
|
import { resolveEndpoint } from '../api/endpoints.js';
|
|
7
|
+
import { withStepUp } from '../core/stepUpPrompt.js';
|
|
8
|
+
import { announce, announceFailure } from '../core/announce.js';
|
|
9
|
+
import { resolveOrgId } from './helpers.js';
|
|
7
10
|
|
|
8
11
|
export function registerAdminCommands(program, ctx) {
|
|
9
12
|
const { client, auth } = ctx;
|
|
@@ -154,6 +157,38 @@ export function registerAdminCommands(program, ctx) {
|
|
|
154
157
|
console.log(data.token);
|
|
155
158
|
});
|
|
156
159
|
|
|
160
|
+
// ADMIN-VERIFY-EMAIL: accounts with no real mailbox (test/service accounts) can never click the
|
|
161
|
+
// emailed link, so they never see org invites. Instance-admin, human, step-up PIN (hidden prompt).
|
|
162
|
+
const users = admin
|
|
163
|
+
.command('users')
|
|
164
|
+
.description('Instance user administration');
|
|
165
|
+
|
|
166
|
+
users
|
|
167
|
+
.command('verify-email')
|
|
168
|
+
.description('Mark a user email verified (instance admin; asks for your step-up PIN; audited)')
|
|
169
|
+
.argument('<email>', 'the email address to mark verified')
|
|
170
|
+
.requiredOption('--reason <text>', 'why this address is verified without a mailbox (recorded in the audit log)')
|
|
171
|
+
.option('--user-id <id>', 'refuse unless the email belongs to this user id')
|
|
172
|
+
.action(async (email, opts) => {
|
|
173
|
+
auth.requireAuth();
|
|
174
|
+
const reason = String(opts.reason || '').trim();
|
|
175
|
+
if (!reason) throw new Error('--reason must not be empty');
|
|
176
|
+
const orgId = resolveOrgId(auth, program);
|
|
177
|
+
const ep = resolveEndpoint('admin.users.verify_email');
|
|
178
|
+
let data;
|
|
179
|
+
try {
|
|
180
|
+
data = await withStepUp(
|
|
181
|
+
(headers) => client.post(ep.path, { service: ep.service, headers, body: { email, reason, ...(opts.userId ? { user_id: opts.userId } : {}) } }),
|
|
182
|
+
{ client, orgId, scope: 'override', io: ctx.stepUpIO, what: 'Verifying an email address' },
|
|
183
|
+
);
|
|
184
|
+
} catch (err) {
|
|
185
|
+
announceFailure('quox', `admin verify-email ${email}`, err);
|
|
186
|
+
throw err;
|
|
187
|
+
}
|
|
188
|
+
announce('quox', `admin verify-email ${email}`, { result: `verified · user ${data.user_id}` });
|
|
189
|
+
printSuccess(`Email ${data.email} is now verified. Reason recorded in the audit log.`);
|
|
190
|
+
});
|
|
191
|
+
|
|
157
192
|
// Email / SMTP (QCPRO-SMTP): instance email onboarding parity
|
|
158
193
|
const email = admin
|
|
159
194
|
.command('email')
|
|
@@ -1322,6 +1322,21 @@ export function registerAgentAttachCommands(agent, ctx, program) {
|
|
|
1322
1322
|
if (program.opts().output === 'json') formatDetail(data, { format: 'json' });
|
|
1323
1323
|
});
|
|
1324
1324
|
|
|
1325
|
+
agent
|
|
1326
|
+
.command('attaches')
|
|
1327
|
+
.description('List every live agent attach in the org (agent, splinter, session, lease, heartbeat, expiry)')
|
|
1328
|
+
.action(async () => {
|
|
1329
|
+
auth.requireAuth();
|
|
1330
|
+
const ep = resolveEndpoint('agent-attach.list');
|
|
1331
|
+
const data = await client.get(ep.path, { service: ep.service });
|
|
1332
|
+
const rows = Array.isArray(data?.attaches) ? data.attaches : [];
|
|
1333
|
+
if (program.opts().output === 'json') return formatDetail(data, { format: 'json' });
|
|
1334
|
+
if (!rows.length) return printInfo('No live agent attaches in this org.');
|
|
1335
|
+
for (const a of rows) {
|
|
1336
|
+
printInfo(`${a.agent_id} ${a.splinter || 'S1'} · ${a.session_label || '(no label)'} · lease ${a.lease_id} · heartbeat ${fmtAge(a.last_heartbeat_at)} · expires ${a.expires_at || '?'}`);
|
|
1337
|
+
}
|
|
1338
|
+
});
|
|
1339
|
+
|
|
1325
1340
|
agent
|
|
1326
1341
|
.command('attach-heartbeat')
|
|
1327
1342
|
.description("Heartbeat this session's attach lease, rotating the stored token if one is issued")
|