@automagik/omni 2.260907.4 → 2.260907.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/multitenancy.d.ts +21 -0
- package/dist/commands/multitenancy.d.ts.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/tenants.d.ts +91 -0
- package/dist/commands/tenants.d.ts.map +1 -0
- package/dist/index.js +412 -5
- package/dist/lib/credential-status.d.ts +18 -0
- package/dist/lib/credential-status.d.ts.map +1 -1
- package/dist/sdk/client.d.ts +98 -0
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +126 -0
- package/dist/sdk/types.generated.d.ts +349 -0
- package/dist/sdk/types.generated.d.ts.map +1 -1
- package/dist/server/index.js +280 -6
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAySpC,wBAAgB,iBAAiB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAySpC,wBAAgB,iBAAiB,IAAI,OAAO,CA+J3C"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multitenancy Commands (read-only; issue #982)
|
|
3
|
+
*
|
|
4
|
+
* omni multitenancy status - Show the server's tenancy posture
|
|
5
|
+
*
|
|
6
|
+
* STRICTLY VISIBILITY, BY DESIGN
|
|
7
|
+
* ------------------------------
|
|
8
|
+
* There is deliberately no `enable`, no cutover, and no write of any kind
|
|
9
|
+
* here: production cutover is receipt-gated and belongs to the separate
|
|
10
|
+
* private production authority. `status` wraps the posture the server already
|
|
11
|
+
* reports on the authenticated `POST /auth/validate` surface — it issues no
|
|
12
|
+
* additional server-side queries.
|
|
13
|
+
*
|
|
14
|
+
* A server that reports no posture is itself an answer: it predates posture
|
|
15
|
+
* reporting (and therefore the tenant control plane), which is one of the
|
|
16
|
+
* three states an operator staring at a `/api/v2/platform` 404 needs to tell
|
|
17
|
+
* apart. That case prints an explanation rather than fabricated defaults.
|
|
18
|
+
*/
|
|
19
|
+
import { Command } from 'commander';
|
|
20
|
+
export declare function createMultitenancyCommand(): Command;
|
|
21
|
+
//# sourceMappingURL=multitenancy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multitenancy.d.ts","sourceRoot":"","sources":["../../src/commands/multitenancy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,yBAAyB,IAAI,OAAO,CAgCnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyLpC,wBAAgB,mBAAmB,IAAI,OAAO,CAU7C"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform Tenant Control-Plane Commands (`omni tenants`)
|
|
3
|
+
*
|
|
4
|
+
* Tenant lifecycle (list/get/create/suspend/archive) and memberships
|
|
5
|
+
* (list/add/disable/status/role) over the platform control plane
|
|
6
|
+
* (issue #981; wish: omni-full-multitenancy, Group G1; ADR-0005).
|
|
7
|
+
*
|
|
8
|
+
* Every command carries an audited `--reason` and refuses to run without it —
|
|
9
|
+
* the server enforces the same rule (reads validate the `x-platform-reason`
|
|
10
|
+
* header, mutations validate body `reason`), but a local check turns a
|
|
11
|
+
* validation 400 into an actionable message before any request is sent.
|
|
12
|
+
*
|
|
13
|
+
* The control plane is feature-flagged server-side: when
|
|
14
|
+
* `OMNI_MULTITENANCY_ENABLED` is not `true` the whole surface 404s, and only
|
|
15
|
+
* PLATFORM-class credentials are accepted. Both failure modes are rendered as
|
|
16
|
+
* explanations, not raw HTTP dumps.
|
|
17
|
+
*
|
|
18
|
+
* The `keys issue-root` subcommand is intentionally absent — the route ships
|
|
19
|
+
* separately (#979) and the subcommand follows it.
|
|
20
|
+
*/
|
|
21
|
+
import { type OmniClient } from '@omni/sdk';
|
|
22
|
+
import { Command } from 'commander';
|
|
23
|
+
interface ReasonOption {
|
|
24
|
+
reason?: string;
|
|
25
|
+
}
|
|
26
|
+
interface CreateOptions extends ReasonOption {
|
|
27
|
+
slug: string;
|
|
28
|
+
name: string;
|
|
29
|
+
maxKeyTtl: number;
|
|
30
|
+
maxKeyRate: number;
|
|
31
|
+
maxKeyBudget: number;
|
|
32
|
+
}
|
|
33
|
+
interface MembershipAddOptions extends ReasonOption {
|
|
34
|
+
principal: string;
|
|
35
|
+
role: string;
|
|
36
|
+
}
|
|
37
|
+
interface MembershipStatusOptions extends ReasonOption {
|
|
38
|
+
status: string;
|
|
39
|
+
}
|
|
40
|
+
interface MembershipRoleOptions extends ReasonOption {
|
|
41
|
+
role: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Enforce the audited `--reason` before any request is sent. The server
|
|
45
|
+
* requires 3-500 characters; mirroring the bounds here keeps the refusal
|
|
46
|
+
* local, immediate, and explained.
|
|
47
|
+
*/
|
|
48
|
+
declare function requireReason(reason: string | undefined, action: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Render a control-plane failure as an explanation, not a raw HTTP dump.
|
|
51
|
+
*
|
|
52
|
+
* - An "Endpoint not found" 404 means the surface is unmounted: multitenancy
|
|
53
|
+
* is disabled (`OMNI_MULTITENANCY_ENABLED`) or the server predates the
|
|
54
|
+
* control plane. Any other 404 is a genuine missing tenant/membership
|
|
55
|
+
* (the API is deliberately non-enumerating there).
|
|
56
|
+
* - 401/403 mean the configured key is not a PLATFORM-class credential with
|
|
57
|
+
* the required scope — tenant and legacy data-plane keys are denied by
|
|
58
|
+
* design, so "log in harder" is not the fix; a platform credential is.
|
|
59
|
+
*/
|
|
60
|
+
declare function renderPlatformError(err: unknown, action: string): never;
|
|
61
|
+
declare function handleList(client: OmniClient, options: ReasonOption): Promise<void>;
|
|
62
|
+
declare function handleGet(client: OmniClient, id: string, options: ReasonOption): Promise<void>;
|
|
63
|
+
declare function handleCreate(client: OmniClient, options: CreateOptions): Promise<void>;
|
|
64
|
+
declare function handleSuspend(client: OmniClient, id: string, options: ReasonOption): Promise<void>;
|
|
65
|
+
declare function handleArchive(client: OmniClient, id: string, options: ReasonOption): Promise<void>;
|
|
66
|
+
declare function handleMembershipsList(client: OmniClient, tenantId: string, options: ReasonOption): Promise<void>;
|
|
67
|
+
declare function handleMembershipsAdd(client: OmniClient, tenantId: string, options: MembershipAddOptions): Promise<void>;
|
|
68
|
+
declare function handleMembershipsDisable(client: OmniClient, tenantId: string, membershipId: string, options: ReasonOption): Promise<void>;
|
|
69
|
+
declare function handleMembershipsStatus(client: OmniClient, tenantId: string, membershipId: string, options: MembershipStatusOptions): Promise<void>;
|
|
70
|
+
declare function handleMembershipsRole(client: OmniClient, tenantId: string, membershipId: string, options: MembershipRoleOptions): Promise<void>;
|
|
71
|
+
export declare function createTenantsCommand(): Command;
|
|
72
|
+
/**
|
|
73
|
+
* Exported for tests — lets us exercise reason enforcement, SDK-call mapping,
|
|
74
|
+
* and control-plane error rendering without reaching into Commander internals.
|
|
75
|
+
*/
|
|
76
|
+
export declare const __testables: {
|
|
77
|
+
requireReason: typeof requireReason;
|
|
78
|
+
renderPlatformError: typeof renderPlatformError;
|
|
79
|
+
handleList: typeof handleList;
|
|
80
|
+
handleGet: typeof handleGet;
|
|
81
|
+
handleCreate: typeof handleCreate;
|
|
82
|
+
handleSuspend: typeof handleSuspend;
|
|
83
|
+
handleArchive: typeof handleArchive;
|
|
84
|
+
handleMembershipsList: typeof handleMembershipsList;
|
|
85
|
+
handleMembershipsAdd: typeof handleMembershipsAdd;
|
|
86
|
+
handleMembershipsDisable: typeof handleMembershipsDisable;
|
|
87
|
+
handleMembershipsStatus: typeof handleMembershipsStatus;
|
|
88
|
+
handleMembershipsRole: typeof handleMembershipsRole;
|
|
89
|
+
};
|
|
90
|
+
export {};
|
|
91
|
+
//# sourceMappingURL=tenants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenants.d.ts","sourceRoot":"","sources":["../../src/commands/tenants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAgB,KAAK,UAAU,EAAsD,MAAM,WAAW,CAAC;AAC9G,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,aAAc,SAAQ,YAAY;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,oBAAqB,SAAQ,YAAY;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,uBAAwB,SAAQ,YAAY;IACpD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,qBAAsB,SAAQ,YAAY;IAClD,IAAI,EAAE,MAAM,CAAC;CACd;AA0BD;;;;GAIG;AACH,iBAAS,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMzE;AAgBD;;;;;;;;;;GAUG;AACH,iBAAS,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAchE;AA8BD,iBAAe,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAOlF;AAED,iBAAe,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7F;AAED,iBAAe,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrF;AAED,iBAAe,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAKjG;AAED,iBAAe,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjG;AAMD,iBAAe,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/G;AAED,iBAAe,oBAAoB,CACjC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CASf;AAED,iBAAe,wBAAwB,CACrC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,iBAAe,uBAAuB,CACpC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,iBAAe,qBAAqB,CAClC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAKf;AAQD,wBAAgB,oBAAoB,IAAI,OAAO,CAqJ9C;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;CAavB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11260,6 +11260,8 @@ var init_types3 = __esm(() => {
|
|
|
11260
11260
|
"message.delivered",
|
|
11261
11261
|
"message.read",
|
|
11262
11262
|
"message.failed",
|
|
11263
|
+
"message.pinned",
|
|
11264
|
+
"message.unpinned",
|
|
11263
11265
|
"message.button_click",
|
|
11264
11266
|
"message.poll",
|
|
11265
11267
|
"message.poll_vote",
|
|
@@ -135775,6 +135777,132 @@ function createOmniClient(config) {
|
|
|
135775
135777
|
throw OmniApiError.from(await resp.json(), resp.status);
|
|
135776
135778
|
}
|
|
135777
135779
|
},
|
|
135780
|
+
platform: {
|
|
135781
|
+
tenants: {
|
|
135782
|
+
async list(reason) {
|
|
135783
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants`, {
|
|
135784
|
+
headers: { "x-platform-reason": reason }
|
|
135785
|
+
});
|
|
135786
|
+
const json = await resp.json();
|
|
135787
|
+
if (!resp.ok)
|
|
135788
|
+
throw OmniApiError.from(json, resp.status);
|
|
135789
|
+
return { items: json?.items ?? [] };
|
|
135790
|
+
},
|
|
135791
|
+
async get(id, reason) {
|
|
135792
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants/${id}`, {
|
|
135793
|
+
headers: { "x-platform-reason": reason }
|
|
135794
|
+
});
|
|
135795
|
+
const json = await resp.json();
|
|
135796
|
+
if (!resp.ok)
|
|
135797
|
+
throw OmniApiError.from(json, resp.status);
|
|
135798
|
+
if (!json?.data)
|
|
135799
|
+
throw new OmniApiError("Tenant not found", "NOT_FOUND", undefined, 404);
|
|
135800
|
+
return json.data;
|
|
135801
|
+
},
|
|
135802
|
+
async create(body) {
|
|
135803
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants`, {
|
|
135804
|
+
method: "POST",
|
|
135805
|
+
headers: { "Content-Type": "application/json" },
|
|
135806
|
+
body: JSON.stringify(body)
|
|
135807
|
+
});
|
|
135808
|
+
const json = await resp.json();
|
|
135809
|
+
if (!resp.ok)
|
|
135810
|
+
throw OmniApiError.from(json, resp.status);
|
|
135811
|
+
if (!json?.data)
|
|
135812
|
+
throw new OmniApiError("Failed to create tenant", "CREATE_FAILED", undefined, resp.status);
|
|
135813
|
+
return json.data;
|
|
135814
|
+
},
|
|
135815
|
+
async suspend(id, reason) {
|
|
135816
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants/${id}/suspend`, {
|
|
135817
|
+
method: "POST",
|
|
135818
|
+
headers: { "Content-Type": "application/json" },
|
|
135819
|
+
body: JSON.stringify({ reason })
|
|
135820
|
+
});
|
|
135821
|
+
const json = await resp.json();
|
|
135822
|
+
if (!resp.ok)
|
|
135823
|
+
throw OmniApiError.from(json, resp.status);
|
|
135824
|
+
if (!json?.data)
|
|
135825
|
+
throw new OmniApiError("Failed to suspend tenant", "SUSPEND_FAILED", undefined, resp.status);
|
|
135826
|
+
return json.data;
|
|
135827
|
+
},
|
|
135828
|
+
async archive(id, reason) {
|
|
135829
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants/${id}/archive`, {
|
|
135830
|
+
method: "POST",
|
|
135831
|
+
headers: { "Content-Type": "application/json" },
|
|
135832
|
+
body: JSON.stringify({ reason })
|
|
135833
|
+
});
|
|
135834
|
+
const json = await resp.json();
|
|
135835
|
+
if (!resp.ok)
|
|
135836
|
+
throw OmniApiError.from(json, resp.status);
|
|
135837
|
+
if (!json?.data)
|
|
135838
|
+
throw new OmniApiError("Failed to archive tenant", "ARCHIVE_FAILED", undefined, resp.status);
|
|
135839
|
+
return json.data;
|
|
135840
|
+
},
|
|
135841
|
+
memberships: {
|
|
135842
|
+
async list(tenantId, reason) {
|
|
135843
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants/${tenantId}/memberships`, {
|
|
135844
|
+
headers: { "x-platform-reason": reason }
|
|
135845
|
+
});
|
|
135846
|
+
const json = await resp.json();
|
|
135847
|
+
if (!resp.ok)
|
|
135848
|
+
throw OmniApiError.from(json, resp.status);
|
|
135849
|
+
return { items: json?.items ?? [] };
|
|
135850
|
+
},
|
|
135851
|
+
async attach(tenantId, body) {
|
|
135852
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants/${tenantId}/memberships`, {
|
|
135853
|
+
method: "POST",
|
|
135854
|
+
headers: { "Content-Type": "application/json" },
|
|
135855
|
+
body: JSON.stringify(body)
|
|
135856
|
+
});
|
|
135857
|
+
const json = await resp.json();
|
|
135858
|
+
if (!resp.ok)
|
|
135859
|
+
throw OmniApiError.from(json, resp.status);
|
|
135860
|
+
if (!json?.data)
|
|
135861
|
+
throw new OmniApiError("Failed to attach membership", "ATTACH_FAILED", undefined, resp.status);
|
|
135862
|
+
return json.data;
|
|
135863
|
+
},
|
|
135864
|
+
async disable(tenantId, membershipId, reason) {
|
|
135865
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants/${tenantId}/memberships/${membershipId}/disable`, {
|
|
135866
|
+
method: "POST",
|
|
135867
|
+
headers: { "Content-Type": "application/json" },
|
|
135868
|
+
body: JSON.stringify({ reason })
|
|
135869
|
+
});
|
|
135870
|
+
const json = await resp.json();
|
|
135871
|
+
if (!resp.ok)
|
|
135872
|
+
throw OmniApiError.from(json, resp.status);
|
|
135873
|
+
if (!json?.data)
|
|
135874
|
+
throw new OmniApiError("Failed to disable membership", "DISABLE_FAILED", undefined, resp.status);
|
|
135875
|
+
return json.data;
|
|
135876
|
+
},
|
|
135877
|
+
async setStatus(tenantId, membershipId, status, reason) {
|
|
135878
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants/${tenantId}/memberships/${membershipId}/status`, {
|
|
135879
|
+
method: "POST",
|
|
135880
|
+
headers: { "Content-Type": "application/json" },
|
|
135881
|
+
body: JSON.stringify({ status, reason })
|
|
135882
|
+
});
|
|
135883
|
+
const json = await resp.json();
|
|
135884
|
+
if (!resp.ok)
|
|
135885
|
+
throw OmniApiError.from(json, resp.status);
|
|
135886
|
+
if (!json?.data)
|
|
135887
|
+
throw new OmniApiError("Failed to set membership status", "STATUS_FAILED", undefined, resp.status);
|
|
135888
|
+
return json.data;
|
|
135889
|
+
},
|
|
135890
|
+
async setRole(tenantId, membershipId, role, reason) {
|
|
135891
|
+
const resp = await apiFetch(`${baseUrl}/api/v2/platform/tenants/${tenantId}/memberships/${membershipId}/role`, {
|
|
135892
|
+
method: "POST",
|
|
135893
|
+
headers: { "Content-Type": "application/json" },
|
|
135894
|
+
body: JSON.stringify({ role, reason })
|
|
135895
|
+
});
|
|
135896
|
+
const json = await resp.json();
|
|
135897
|
+
if (!resp.ok)
|
|
135898
|
+
throw OmniApiError.from(json, resp.status);
|
|
135899
|
+
if (!json?.data)
|
|
135900
|
+
throw new OmniApiError("Failed to set membership role", "ROLE_FAILED", undefined, resp.status);
|
|
135901
|
+
return json.data;
|
|
135902
|
+
}
|
|
135903
|
+
}
|
|
135904
|
+
}
|
|
135905
|
+
},
|
|
135778
135906
|
context: {
|
|
135779
135907
|
async get() {
|
|
135780
135908
|
const resp = await apiFetch(`${baseUrl}/api/v2/context`, {});
|
|
@@ -136390,7 +136518,7 @@ import { fileURLToPath } from "url";
|
|
|
136390
136518
|
// package.json
|
|
136391
136519
|
var package_default = {
|
|
136392
136520
|
name: "@automagik/omni",
|
|
136393
|
-
version: "2.260907.
|
|
136521
|
+
version: "2.260907.6",
|
|
136394
136522
|
repository: {
|
|
136395
136523
|
type: "git",
|
|
136396
136524
|
url: "git+https://github.com/automagik-dev/omni.git",
|
|
@@ -137596,6 +137724,20 @@ function credentialStatusFields(auth) {
|
|
|
137596
137724
|
delegationDepth: credential.delegationDepth
|
|
137597
137725
|
};
|
|
137598
137726
|
}
|
|
137727
|
+
function serverPostureFields(auth) {
|
|
137728
|
+
const posture = auth.server;
|
|
137729
|
+
if (!posture)
|
|
137730
|
+
return {};
|
|
137731
|
+
const fields = {
|
|
137732
|
+
serverMultitenancy: posture.multitenancyEnabled ? "enabled" : "disabled",
|
|
137733
|
+
serverControlPlane: posture.controlPlaneMounted ? "mounted" : "not mounted",
|
|
137734
|
+
serverDbEnforcement: posture.dbEnforcement
|
|
137735
|
+
};
|
|
137736
|
+
if (posture.multitenancyEnabled && posture.dbEnforcement === "legacy") {
|
|
137737
|
+
fields.tenancyWarning = "isolation not enforced: multitenancy is enabled but DB enforcement is legacy \u2014 the tenant boundary is advisory only (migration state)";
|
|
137738
|
+
}
|
|
137739
|
+
return fields;
|
|
137740
|
+
}
|
|
137599
137741
|
|
|
137600
137742
|
// src/commands/auth.ts
|
|
137601
137743
|
init_output();
|
|
@@ -138290,6 +138432,7 @@ one, or the entry named by the global flag:
|
|
|
138290
138432
|
keyPrefix: result.keyPrefix,
|
|
138291
138433
|
scopes: result.scopes,
|
|
138292
138434
|
...credentialStatusFields(result),
|
|
138435
|
+
...serverPostureFields(result),
|
|
138293
138436
|
configDir: getConfigDir()
|
|
138294
138437
|
});
|
|
138295
138438
|
} catch (err) {
|
|
@@ -146494,6 +146637,30 @@ async function handleCloseContact(options) {
|
|
|
146494
146637
|
}
|
|
146495
146638
|
}
|
|
146496
146639
|
|
|
146640
|
+
// src/commands/multitenancy.ts
|
|
146641
|
+
init_output();
|
|
146642
|
+
function createMultitenancyCommand() {
|
|
146643
|
+
const multitenancy = new Command("multitenancy").description("Multitenancy posture (read-only)");
|
|
146644
|
+
multitenancy.command("status").description("Show the server's multitenancy flag, control plane, and DB enforcement posture").action(async () => {
|
|
146645
|
+
const client = getClient();
|
|
146646
|
+
try {
|
|
146647
|
+
const result = await client.auth.validate();
|
|
146648
|
+
if (!result.server) {
|
|
146649
|
+
data({
|
|
146650
|
+
posture: "unreported",
|
|
146651
|
+
note: "This server does not report tenancy posture \u2014 it predates posture reporting " + "(and likely the tenant control plane). Platform commands will 404 regardless of flags. " + "Upgrade the server to get posture visibility."
|
|
146652
|
+
});
|
|
146653
|
+
return;
|
|
146654
|
+
}
|
|
146655
|
+
data(serverPostureFields(result));
|
|
146656
|
+
} catch (err2) {
|
|
146657
|
+
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
146658
|
+
error(`Failed to read server posture: ${message2}`, undefined, 2);
|
|
146659
|
+
}
|
|
146660
|
+
});
|
|
146661
|
+
return multitenancy;
|
|
146662
|
+
}
|
|
146663
|
+
|
|
146497
146664
|
// src/commands/music.ts
|
|
146498
146665
|
import { writeFileSync as writeFileSync9 } from "fs";
|
|
146499
146666
|
import { resolve as resolvePath2 } from "path";
|
|
@@ -149601,6 +149768,7 @@ async function validateAuthKey(statusInfo, client) {
|
|
|
149601
149768
|
statusInfo.keyPrefix = auth.keyPrefix;
|
|
149602
149769
|
statusInfo.scopes = auth.scopes;
|
|
149603
149770
|
Object.assign(statusInfo, credentialStatusFields(auth));
|
|
149771
|
+
Object.assign(statusInfo, serverPostureFields(auth));
|
|
149604
149772
|
} catch {
|
|
149605
149773
|
statusInfo.keyValid = false;
|
|
149606
149774
|
}
|
|
@@ -149672,6 +149840,233 @@ function createStopCommand() {
|
|
|
149672
149840
|
return new Command("stop").description("Stop all omni PM2 processes").action(runStop);
|
|
149673
149841
|
}
|
|
149674
149842
|
|
|
149843
|
+
// src/commands/tenants.ts
|
|
149844
|
+
init_output();
|
|
149845
|
+
var TENANT_ROLES = ["tenant-owner", "tenant-admin", "tenant-operator", "tenant-viewer"];
|
|
149846
|
+
var MEMBERSHIP_STATUSES = ["active", "disabled"];
|
|
149847
|
+
var REASON_REQUIRED_HINT = "Every platform control-plane call is audited; " + 'provide a justification of 3-500 characters, e.g. --reason "onboarding request OPS-1421".';
|
|
149848
|
+
var CONTROL_PLANE_UNAVAILABLE = "the platform control plane is not available on this server. " + "Either multitenancy is disabled (start the API with OMNI_MULTITENANCY_ENABLED=true) " + "or the server predates the tenant control plane \u2014 upgrade it.";
|
|
149849
|
+
var CREDENTIAL_REJECTED_401 = "the server rejected the credential (401). " + "The platform control plane accepts only PLATFORM-class credentials \u2014 legacy admin/god keys and " + "tenant data-plane keys are denied by design. Authenticate with a platform key: " + "omni auth login --api-key <platform-key>.";
|
|
149850
|
+
var CREDENTIAL_FORBIDDEN_403 = "the credential authenticated but is not allowed (403). " + "A PLATFORM-class credential with the matching platform:* scope is required \u2014 tenant-class " + "credentials can never reach the control plane, and platform keys act only within their scopes.";
|
|
149851
|
+
function requireReason(reason, action) {
|
|
149852
|
+
const trimmed = reason?.trim() ?? "";
|
|
149853
|
+
if (trimmed.length < 3 || trimmed.length > 500) {
|
|
149854
|
+
error(`--reason is required to ${action}. ${REASON_REQUIRED_HINT}`, undefined, 1);
|
|
149855
|
+
}
|
|
149856
|
+
return trimmed;
|
|
149857
|
+
}
|
|
149858
|
+
function parseRole(value) {
|
|
149859
|
+
if (!TENANT_ROLES.includes(value)) {
|
|
149860
|
+
error(`Invalid --role "${value}". Valid roles: ${TENANT_ROLES.join(", ")}`, undefined, 1);
|
|
149861
|
+
}
|
|
149862
|
+
return value;
|
|
149863
|
+
}
|
|
149864
|
+
function parseStatus(value) {
|
|
149865
|
+
if (!MEMBERSHIP_STATUSES.includes(value)) {
|
|
149866
|
+
error(`Invalid --status "${value}". Valid statuses: ${MEMBERSHIP_STATUSES.join(", ")}`, undefined, 1);
|
|
149867
|
+
}
|
|
149868
|
+
return value;
|
|
149869
|
+
}
|
|
149870
|
+
function renderPlatformError(err2, action) {
|
|
149871
|
+
if (err2 instanceof OmniApiError) {
|
|
149872
|
+
if (err2.status === 404 && err2.message.startsWith("Endpoint not found")) {
|
|
149873
|
+
error(`Failed to ${action}: ${CONTROL_PLANE_UNAVAILABLE}`, undefined, 1);
|
|
149874
|
+
}
|
|
149875
|
+
if (err2.status === 401) {
|
|
149876
|
+
error(`Failed to ${action}: ${CREDENTIAL_REJECTED_401}`, undefined, 1);
|
|
149877
|
+
}
|
|
149878
|
+
if (err2.status === 403) {
|
|
149879
|
+
error(`Failed to ${action}: ${CREDENTIAL_FORBIDDEN_403}`, undefined, 1);
|
|
149880
|
+
}
|
|
149881
|
+
}
|
|
149882
|
+
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
149883
|
+
error(`Failed to ${action}: ${message2}`);
|
|
149884
|
+
}
|
|
149885
|
+
function formatTenantRow(tenant) {
|
|
149886
|
+
return {
|
|
149887
|
+
id: tenant.id,
|
|
149888
|
+
slug: tenant.slug,
|
|
149889
|
+
name: tenant.displayName,
|
|
149890
|
+
status: tenant.status,
|
|
149891
|
+
keyTtl: tenant.maxKeyTtlSeconds,
|
|
149892
|
+
keyRate: tenant.maxKeyRateLimit,
|
|
149893
|
+
keyBudget: tenant.maxKeyBudget,
|
|
149894
|
+
created: new Date(tenant.createdAt).toLocaleDateString()
|
|
149895
|
+
};
|
|
149896
|
+
}
|
|
149897
|
+
function formatMembershipRow(membership) {
|
|
149898
|
+
return {
|
|
149899
|
+
id: membership.id,
|
|
149900
|
+
principal: membership.principalId,
|
|
149901
|
+
role: membership.role,
|
|
149902
|
+
status: membership.status,
|
|
149903
|
+
invitedBy: membership.invitedByPrincipalId ?? "-",
|
|
149904
|
+
created: new Date(membership.createdAt).toLocaleDateString()
|
|
149905
|
+
};
|
|
149906
|
+
}
|
|
149907
|
+
async function handleList5(client, options3) {
|
|
149908
|
+
const reason = requireReason(options3.reason, "list tenants");
|
|
149909
|
+
const result = await client.platform.tenants.list(reason);
|
|
149910
|
+
list(result.items.map(formatTenantRow), {
|
|
149911
|
+
emptyMessage: "No tenants found.",
|
|
149912
|
+
rawData: result.items
|
|
149913
|
+
});
|
|
149914
|
+
}
|
|
149915
|
+
async function handleGet3(client, id, options3) {
|
|
149916
|
+
const reason = requireReason(options3.reason, "read a tenant");
|
|
149917
|
+
const tenant = await client.platform.tenants.get(id, reason);
|
|
149918
|
+
data(tenant);
|
|
149919
|
+
}
|
|
149920
|
+
async function handleCreate4(client, options3) {
|
|
149921
|
+
const reason = requireReason(options3.reason, "create a tenant");
|
|
149922
|
+
const tenant = await client.platform.tenants.create({
|
|
149923
|
+
slug: options3.slug,
|
|
149924
|
+
displayName: options3.name,
|
|
149925
|
+
maxKeyTtlSeconds: options3.maxKeyTtl,
|
|
149926
|
+
maxKeyRateLimit: options3.maxKeyRate,
|
|
149927
|
+
maxKeyBudget: options3.maxKeyBudget,
|
|
149928
|
+
reason
|
|
149929
|
+
});
|
|
149930
|
+
success(`Tenant created: ${tenant.slug} (${tenant.id})`);
|
|
149931
|
+
data(tenant);
|
|
149932
|
+
}
|
|
149933
|
+
async function handleSuspend(client, id, options3) {
|
|
149934
|
+
const reason = requireReason(options3.reason, "suspend a tenant");
|
|
149935
|
+
const tenant = await client.platform.tenants.suspend(id, reason);
|
|
149936
|
+
success(`Tenant suspended: ${tenant.slug} (${tenant.id})`);
|
|
149937
|
+
info(`Reason: ${reason}`);
|
|
149938
|
+
}
|
|
149939
|
+
async function handleArchive(client, id, options3) {
|
|
149940
|
+
const reason = requireReason(options3.reason, "archive a tenant");
|
|
149941
|
+
const tenant = await client.platform.tenants.archive(id, reason);
|
|
149942
|
+
success(`Tenant archived: ${tenant.slug} (${tenant.id})`);
|
|
149943
|
+
warn("Archived is terminal \u2014 there is no un-archive and no hard delete.");
|
|
149944
|
+
info(`Reason: ${reason}`);
|
|
149945
|
+
}
|
|
149946
|
+
async function handleMembershipsList(client, tenantId, options3) {
|
|
149947
|
+
const reason = requireReason(options3.reason, "list memberships");
|
|
149948
|
+
const result = await client.platform.tenants.memberships.list(tenantId, reason);
|
|
149949
|
+
list(result.items.map(formatMembershipRow), {
|
|
149950
|
+
emptyMessage: "No memberships found.",
|
|
149951
|
+
rawData: result.items
|
|
149952
|
+
});
|
|
149953
|
+
}
|
|
149954
|
+
async function handleMembershipsAdd(client, tenantId, options3) {
|
|
149955
|
+
const reason = requireReason(options3.reason, "attach a membership");
|
|
149956
|
+
const role = parseRole(options3.role);
|
|
149957
|
+
const membership = await client.platform.tenants.memberships.attach(tenantId, {
|
|
149958
|
+
principalId: options3.principal,
|
|
149959
|
+
role,
|
|
149960
|
+
reason
|
|
149961
|
+
});
|
|
149962
|
+
success(`Membership attached: ${membership.principalId} as ${membership.role} (${membership.id})`);
|
|
149963
|
+
}
|
|
149964
|
+
async function handleMembershipsDisable(client, tenantId, membershipId, options3) {
|
|
149965
|
+
const reason = requireReason(options3.reason, "disable a membership");
|
|
149966
|
+
const membership = await client.platform.tenants.memberships.disable(tenantId, membershipId, reason);
|
|
149967
|
+
success(`Membership disabled: ${membership.id}`);
|
|
149968
|
+
info(`Reason: ${reason}`);
|
|
149969
|
+
}
|
|
149970
|
+
async function handleMembershipsStatus(client, tenantId, membershipId, options3) {
|
|
149971
|
+
const reason = requireReason(options3.reason, "set a membership status");
|
|
149972
|
+
const status = parseStatus(options3.status);
|
|
149973
|
+
const membership = await client.platform.tenants.memberships.setStatus(tenantId, membershipId, status, reason);
|
|
149974
|
+
success(`Membership ${membership.id} status set to ${membership.status}`);
|
|
149975
|
+
}
|
|
149976
|
+
async function handleMembershipsRole(client, tenantId, membershipId, options3) {
|
|
149977
|
+
const reason = requireReason(options3.reason, "set a membership role");
|
|
149978
|
+
const role = parseRole(options3.role);
|
|
149979
|
+
const membership = await client.platform.tenants.memberships.setRole(tenantId, membershipId, role, reason);
|
|
149980
|
+
success(`Membership ${membership.id} role set to ${membership.role}`);
|
|
149981
|
+
}
|
|
149982
|
+
var REASON_HELP = "Audited justification (required, 3-500 chars)";
|
|
149983
|
+
function createTenantsCommand() {
|
|
149984
|
+
const tenants2 = new Command("tenants").description("Platform tenant control plane (requires a PLATFORM-class credential and OMNI_MULTITENANCY_ENABLED=true)");
|
|
149985
|
+
tenants2.command("list").description("List tenants, newest first (the read itself is audited)").option("--reason <text>", REASON_HELP).action(async (options3) => {
|
|
149986
|
+
const client = getClient();
|
|
149987
|
+
try {
|
|
149988
|
+
await handleList5(client, options3);
|
|
149989
|
+
} catch (err2) {
|
|
149990
|
+
renderPlatformError(err2, "list tenants");
|
|
149991
|
+
}
|
|
149992
|
+
});
|
|
149993
|
+
tenants2.command("get <id>").description("Get one tenant by id").option("--reason <text>", REASON_HELP).action(async (id, options3) => {
|
|
149994
|
+
const client = getClient();
|
|
149995
|
+
try {
|
|
149996
|
+
await handleGet3(client, id, options3);
|
|
149997
|
+
} catch (err2) {
|
|
149998
|
+
renderPlatformError(err2, "get the tenant");
|
|
149999
|
+
}
|
|
150000
|
+
});
|
|
150001
|
+
tenants2.command("create").description("Create a tenant with its mandatory credential ceilings").requiredOption("--slug <slug>", "Immutable lowercase DNS-like slug (e.g. acme)").requiredOption("--name <name>", "Human-readable tenant name").requiredOption("--max-key-ttl <seconds>", "Ceiling for credential TTL, in seconds", Number.parseInt).requiredOption("--max-key-rate <n>", "Ceiling for credential rate limit", Number.parseInt).requiredOption("--max-key-budget <n>", "Ceiling for credential budget", Number.parseInt).option("--reason <text>", REASON_HELP).action(async (options3) => {
|
|
150002
|
+
const client = getClient();
|
|
150003
|
+
try {
|
|
150004
|
+
await handleCreate4(client, options3);
|
|
150005
|
+
} catch (err2) {
|
|
150006
|
+
renderPlatformError(err2, "create the tenant");
|
|
150007
|
+
}
|
|
150008
|
+
});
|
|
150009
|
+
tenants2.command("suspend <id>").description("Suspend a tenant (bumps its revocation epoch, invalidating tenant credentials)").option("--reason <text>", REASON_HELP).action(async (id, options3) => {
|
|
150010
|
+
const client = getClient();
|
|
150011
|
+
try {
|
|
150012
|
+
await handleSuspend(client, id, options3);
|
|
150013
|
+
} catch (err2) {
|
|
150014
|
+
renderPlatformError(err2, "suspend the tenant");
|
|
150015
|
+
}
|
|
150016
|
+
});
|
|
150017
|
+
tenants2.command("archive <id>").description("Archive a tenant (TERMINAL \u2014 no un-archive, no hard delete)").option("--reason <text>", REASON_HELP).action(async (id, options3) => {
|
|
150018
|
+
const client = getClient();
|
|
150019
|
+
try {
|
|
150020
|
+
await handleArchive(client, id, options3);
|
|
150021
|
+
} catch (err2) {
|
|
150022
|
+
renderPlatformError(err2, "archive the tenant");
|
|
150023
|
+
}
|
|
150024
|
+
});
|
|
150025
|
+
const memberships = new Command("memberships").description("Manage tenant memberships");
|
|
150026
|
+
memberships.command("list <tenant-id>").description("List the memberships of one tenant (the read itself is audited)").option("--reason <text>", REASON_HELP).action(async (tenantId, options3) => {
|
|
150027
|
+
const client = getClient();
|
|
150028
|
+
try {
|
|
150029
|
+
await handleMembershipsList(client, tenantId, options3);
|
|
150030
|
+
} catch (err2) {
|
|
150031
|
+
renderPlatformError(err2, "list memberships");
|
|
150032
|
+
}
|
|
150033
|
+
});
|
|
150034
|
+
memberships.command("add <tenant-id>").description("Grant a principal a role in the tenant").requiredOption("--principal <uuid>", "Principal to grant access to").requiredOption("--role <role>", `Tenant role: ${TENANT_ROLES.join(" | ")}`).option("--reason <text>", REASON_HELP).action(async (tenantId, options3) => {
|
|
150035
|
+
const client = getClient();
|
|
150036
|
+
try {
|
|
150037
|
+
await handleMembershipsAdd(client, tenantId, options3);
|
|
150038
|
+
} catch (err2) {
|
|
150039
|
+
renderPlatformError(err2, "attach the membership");
|
|
150040
|
+
}
|
|
150041
|
+
});
|
|
150042
|
+
memberships.command("disable <tenant-id> <membership-id>").description("Disable a membership (memberships are never hard-deleted)").option("--reason <text>", REASON_HELP).action(async (tenantId, membershipId, options3) => {
|
|
150043
|
+
const client = getClient();
|
|
150044
|
+
try {
|
|
150045
|
+
await handleMembershipsDisable(client, tenantId, membershipId, options3);
|
|
150046
|
+
} catch (err2) {
|
|
150047
|
+
renderPlatformError(err2, "disable the membership");
|
|
150048
|
+
}
|
|
150049
|
+
});
|
|
150050
|
+
memberships.command("status <tenant-id> <membership-id>").description("Activate or disable an existing membership").requiredOption("--status <status>", `New status: ${MEMBERSHIP_STATUSES.join(" | ")}`).option("--reason <text>", REASON_HELP).action(async (tenantId, membershipId, options3) => {
|
|
150051
|
+
const client = getClient();
|
|
150052
|
+
try {
|
|
150053
|
+
await handleMembershipsStatus(client, tenantId, membershipId, options3);
|
|
150054
|
+
} catch (err2) {
|
|
150055
|
+
renderPlatformError(err2, "set the membership status");
|
|
150056
|
+
}
|
|
150057
|
+
});
|
|
150058
|
+
memberships.command("role <tenant-id> <membership-id>").description("Change the role an existing membership acts under").requiredOption("--role <role>", `New role: ${TENANT_ROLES.join(" | ")}`).option("--reason <text>", REASON_HELP).action(async (tenantId, membershipId, options3) => {
|
|
150059
|
+
const client = getClient();
|
|
150060
|
+
try {
|
|
150061
|
+
await handleMembershipsRole(client, tenantId, membershipId, options3);
|
|
150062
|
+
} catch (err2) {
|
|
150063
|
+
renderPlatformError(err2, "set the membership role");
|
|
150064
|
+
}
|
|
150065
|
+
});
|
|
150066
|
+
tenants2.addCommand(memberships);
|
|
150067
|
+
return tenants2;
|
|
150068
|
+
}
|
|
150069
|
+
|
|
149675
150070
|
// src/commands/trust.ts
|
|
149676
150071
|
import { hostname as osHostname } from "os";
|
|
149677
150072
|
init_config();
|
|
@@ -149731,7 +150126,7 @@ function formatHostRow(host) {
|
|
|
149731
150126
|
status: host.revokedAt ? "revoked" : "active"
|
|
149732
150127
|
};
|
|
149733
150128
|
}
|
|
149734
|
-
async function
|
|
150129
|
+
async function handleList6() {
|
|
149735
150130
|
try {
|
|
149736
150131
|
const { items } = await callApi("GET", "/hosts");
|
|
149737
150132
|
list(items.map(formatHostRow), {
|
|
@@ -149742,7 +150137,7 @@ async function handleList5() {
|
|
|
149742
150137
|
error(`Failed to list genie hosts: ${err2 instanceof Error ? err2.message : "Unknown error"}`);
|
|
149743
150138
|
}
|
|
149744
150139
|
}
|
|
149745
|
-
async function
|
|
150140
|
+
async function handleGet4(id) {
|
|
149746
150141
|
try {
|
|
149747
150142
|
const { data: data2 } = await callApi("GET", `/hosts/${encodeURIComponent(id)}`);
|
|
149748
150143
|
data(data2);
|
|
@@ -149845,8 +150240,8 @@ Signing is per-server: only servers you have handshaken against recognize this
|
|
|
149845
150240
|
keypair, so calls to other entries stay bearer-only. Bind another one with:
|
|
149846
150241
|
omni trust handshake --server <name>
|
|
149847
150242
|
`).option("--rotate", "Issue a new keypair even if one already exists (unbinds every previously bound server)").option("--hostname <name>", "Override the hostname reported to omni (defaults to os.hostname())").action(handleHandshake);
|
|
149848
|
-
trust.command("list").description("List active (non-revoked) genie hosts").action(
|
|
149849
|
-
trust.command("get <id>").description("Show details for one genie host (active or revoked)").action(
|
|
150243
|
+
trust.command("list").description("List active (non-revoked) genie hosts").action(handleList6);
|
|
150244
|
+
trust.command("get <id>").description("Show details for one genie host (active or revoked)").action(handleGet4);
|
|
149850
150245
|
trust.command("update <id>").description("Replace a genie host scopes (comma-separated)").requiredOption("--scope <list>", 'Comma-separated scope list, e.g. "agents:write,providers:write"').action(handleUpdate3);
|
|
149851
150246
|
trust.command("revoke <id>").description("Revoke a genie host (irreversible \u2014 re-register with a fresh keypair to restore trust)").action(handleRevoke2);
|
|
149852
150247
|
return trust;
|
|
@@ -151716,6 +152111,12 @@ var COMMANDS = [
|
|
|
151716
152111
|
helpGroup: "Management",
|
|
151717
152112
|
helpDescription: "API key management"
|
|
151718
152113
|
},
|
|
152114
|
+
{
|
|
152115
|
+
create: createTenantsCommand,
|
|
152116
|
+
category: "advanced",
|
|
152117
|
+
helpGroup: "Management",
|
|
152118
|
+
helpDescription: "Platform tenant control plane (multitenancy)"
|
|
152119
|
+
},
|
|
151719
152120
|
{
|
|
151720
152121
|
create: createTrustCommand,
|
|
151721
152122
|
category: "advanced",
|
|
@@ -151754,6 +152155,12 @@ var COMMANDS = [
|
|
|
151754
152155
|
},
|
|
151755
152156
|
{ create: createEventsCommand, category: "standard", helpGroup: "System", helpDescription: "Query message history" },
|
|
151756
152157
|
{ create: createAuthCommand, category: "core", helpGroup: "System", helpDescription: "Authentication management" },
|
|
152158
|
+
{
|
|
152159
|
+
create: createMultitenancyCommand,
|
|
152160
|
+
category: "advanced",
|
|
152161
|
+
helpGroup: "System",
|
|
152162
|
+
helpDescription: "Server multitenancy posture (read-only)"
|
|
152163
|
+
},
|
|
151757
152164
|
{
|
|
151758
152165
|
create: createServerCommand,
|
|
151759
152166
|
category: "core",
|
|
@@ -25,4 +25,22 @@ import type { AuthValidateResponse } from '@omni/sdk';
|
|
|
25
25
|
* the legacy projection the surrounding output already prints.
|
|
26
26
|
*/
|
|
27
27
|
export declare function credentialStatusFields(auth: AuthValidateResponse): Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Project the server's tenancy posture into display fields (issue #982).
|
|
30
|
+
*
|
|
31
|
+
* Same empty-object contract as above, for the same reason: a server that does
|
|
32
|
+
* not report posture — any server predating it — must add NOTHING, so output
|
|
33
|
+
* against an old server stays field-for-field what it is today. "Absent" is
|
|
34
|
+
* itself the operator's signal that the server predates the control plane.
|
|
35
|
+
*
|
|
36
|
+
* Field names are prefixed `server*` so they cannot collide with the
|
|
37
|
+
* credential projection or the existing status fields (`omni auth status`
|
|
38
|
+
* already prints a `server` key naming the config entry).
|
|
39
|
+
*
|
|
40
|
+
* The `tenancyWarning` field mirrors `mixedTenancyStateWarning` semantics on
|
|
41
|
+
* the API side: it appears exactly when the flag is on but the database is in
|
|
42
|
+
* legacy enforcement — the advisory-only migration state — and never in the
|
|
43
|
+
* three coherent combinations.
|
|
44
|
+
*/
|
|
45
|
+
export declare function serverPostureFields(auth: AuthValidateResponse): Record<string, unknown>;
|
|
28
46
|
//# sourceMappingURL=credential-status.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential-status.d.ts","sourceRoot":"","sources":["../../src/lib/credential-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgB1F"}
|
|
1
|
+
{"version":3,"file":"credential-status.d.ts","sourceRoot":"","sources":["../../src/lib/credential-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgB1F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBvF"}
|