@opengeni/db 3.2.0-canary.0 → 3.4.0-canary.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/dist/canonical-human-identities.js +3 -3
- package/dist/{chunk-SIBYBA2D.js → chunk-6DPJA36C.js} +30 -11
- package/dist/chunk-6DPJA36C.js.map +1 -0
- package/dist/{chunk-KRLPEMLH.js → chunk-C2AFP7SB.js} +184 -6
- package/dist/chunk-C2AFP7SB.js.map +1 -0
- package/dist/{chunk-AZHW7R5V.js → chunk-H7MXYG7R.js} +12 -8
- package/dist/chunk-H7MXYG7R.js.map +1 -0
- package/dist/{chunk-2PRS4J5Q.js → chunk-HY3F5Q4E.js} +3 -3
- package/dist/{chunk-NAB6FKFN.js → chunk-O6FTELKH.js} +3 -3
- package/dist/{chunk-UZNXG44K.js → chunk-PYMY3AJW.js} +324 -8
- package/dist/chunk-PYMY3AJW.js.map +1 -0
- package/dist/{chunk-6HMM2R5T.js → chunk-TRBOWUG3.js} +98 -4
- package/dist/chunk-TRBOWUG3.js.map +1 -0
- package/dist/{chunk-E6CLMKEE.js → chunk-V3TRUXFJ.js} +2 -2
- package/dist/{chunk-2EH4WRHL.js → chunk-ZWRIPCTR.js} +2 -2
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/governed-learning-activation.d.ts +16 -0
- package/dist/index.d.ts +108 -7
- package/dist/index.js +3605 -1417
- package/dist/index.js.map +1 -1
- package/dist/insights-model-bundle.d.ts +30 -0
- package/dist/insights-usage-bundle.d.ts +32 -0
- package/dist/insights.d.ts +10 -2
- package/dist/lossless-json.d.ts +1 -1
- package/dist/managed-user-setup.d.ts +82 -0
- package/dist/memory-domain.d.ts +2 -2
- package/dist/migrate.d.ts +3 -1
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +4 -4
- package/dist/organization-membership-lifecycle.d.ts +60 -1
- package/dist/pr-review.d.ts +44 -3
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +12 -7
- package/dist/schema.d.ts +839 -101
- package/dist/schema.js +9 -1
- package/dist/session-background-commands.js +3 -3
- package/dist/session-tenancy.d.ts +12 -1
- package/dist/session-tenancy.js +3 -3
- package/dist/video-generation.js +3 -3
- package/drizzle/0348_named_signup_and_user_setup.sql +838 -0
- package/drizzle/0349_greenfield_session_tenancy_activation.sql +792 -0
- package/drizzle/0350_organization_shared_workspace_administration.sql +889 -0
- package/drizzle/0351_organization_user_setup_delivery.sql +978 -0
- package/drizzle/0352_session_variable_set_attachments.sql +1661 -0
- package/drizzle/0353_automatic_session_title_policy_fence.sql +476 -0
- package/drizzle/0354_automatic_session_title_quarantine_index.sql +9 -0
- package/drizzle/0355_automatic_session_title_quarantine.sql +92 -0
- package/drizzle/0356_set_based_insights_session_visibility.sql +237 -0
- package/drizzle/0357_rig_platform_base_only.sql +44 -0
- package/drizzle/0358_pr_review_managed_github_app.sql +108 -0
- package/drizzle/0359_insights_force_rls_read_capability.sql +936 -0
- package/drizzle/0360_organization_identity_confirmation_prompt.sql +103 -0
- package/drizzle/0361_remember_knowledge_memory_materialization.sql +249 -0
- package/package.json +6 -6
- package/src/database.ts +12 -8
- package/src/governed-learning-activation.ts +74 -2
- package/src/index.ts +879 -92
- package/src/insights-model-bundle.ts +681 -0
- package/src/insights-usage-bundle.ts +240 -0
- package/src/insights.ts +265 -152
- package/src/lossless-json.ts +2 -1
- package/src/managed-user-setup.ts +316 -0
- package/src/memory-domain.ts +3 -3
- package/src/migrate.ts +38 -14
- package/src/new-session-drafts.ts +22 -15
- package/src/organization-membership-lifecycle.ts +253 -1
- package/src/pr-review.ts +449 -6
- package/src/provision-roles.ts +92 -0
- package/src/runtime-posture.ts +247 -4
- package/src/schema.ts +210 -4
- package/src/session-tenancy.ts +120 -2
- package/dist/chunk-6HMM2R5T.js.map +0 -1
- package/dist/chunk-AZHW7R5V.js.map +0 -1
- package/dist/chunk-KRLPEMLH.js.map +0 -1
- package/dist/chunk-SIBYBA2D.js.map +0 -1
- package/dist/chunk-UZNXG44K.js.map +0 -1
- /package/dist/{chunk-2PRS4J5Q.js.map → chunk-HY3F5Q4E.js.map} +0 -0
- /package/dist/{chunk-NAB6FKFN.js.map → chunk-O6FTELKH.js.map} +0 -0
- /package/dist/{chunk-E6CLMKEE.js.map → chunk-V3TRUXFJ.js.map} +0 -0
- /package/dist/{chunk-2EH4WRHL.js.map → chunk-ZWRIPCTR.js.map} +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CreateOrganizationResponse,
|
|
3
|
+
ListOrganizationAdministrationMembersResponse,
|
|
3
4
|
ListOrganizationInvitationsResponse,
|
|
4
5
|
ListOrganizationInvitationsPageResponse,
|
|
5
6
|
ListOrganizationMembersResponse,
|
|
6
7
|
ListSelfOrganizationMembershipsResponse,
|
|
7
8
|
OrganizationInvitation,
|
|
8
9
|
OrganizationAdministrationOverview,
|
|
10
|
+
OrganizationWorkspaceAccess,
|
|
9
11
|
OrganizationPrivateSessionSettings,
|
|
10
12
|
OrganizationMember,
|
|
11
13
|
OrganizationRetentionDeletionClaim,
|
|
@@ -15,7 +17,9 @@ import {
|
|
|
15
17
|
OrganizationRetentionDeletionResult,
|
|
16
18
|
OrganizationRetentionPolicy,
|
|
17
19
|
OrganizationSummary,
|
|
20
|
+
RevokeOrganizationWorkspaceMemberResponse,
|
|
18
21
|
type CreateOrganizationResponse as CreateOrganizationResponseType,
|
|
22
|
+
type OrganizationAdministrationMember as OrganizationAdministrationMemberType,
|
|
19
23
|
type OrganizationAdministrationOverview as OrganizationAdministrationOverviewType,
|
|
20
24
|
type OrganizationInvitation as OrganizationInvitationType,
|
|
21
25
|
type OrganizationMember as OrganizationMemberType,
|
|
@@ -28,6 +32,9 @@ import {
|
|
|
28
32
|
type OrganizationRetentionDeletionResult as OrganizationRetentionDeletionResultType,
|
|
29
33
|
type OrganizationRetentionPolicy as OrganizationRetentionPolicyType,
|
|
30
34
|
type OrganizationSummary as OrganizationSummaryType,
|
|
35
|
+
type OrganizationWorkspaceAccess as OrganizationWorkspaceAccessType,
|
|
36
|
+
type PutOrganizationWorkspaceMemberRequest,
|
|
37
|
+
type RevokeOrganizationWorkspaceMemberResponse as RevokeOrganizationWorkspaceMemberResponseType,
|
|
31
38
|
type UpdateOrganizationMemberRequest,
|
|
32
39
|
} from "@opengeni/contracts";
|
|
33
40
|
import { and, eq, sql } from "drizzle-orm";
|
|
@@ -317,6 +324,7 @@ export async function removeWorkspaceMember(
|
|
|
317
324
|
actorSubjectId: string;
|
|
318
325
|
targetSubjectId: string;
|
|
319
326
|
requireOrganizationSharedWorkspaceAdministration?: boolean;
|
|
327
|
+
operationId?: string;
|
|
320
328
|
},
|
|
321
329
|
): Promise<boolean> {
|
|
322
330
|
const command = {
|
|
@@ -325,7 +333,7 @@ export async function removeWorkspaceMember(
|
|
|
325
333
|
workspaceId: input.workspaceId,
|
|
326
334
|
actorSubjectId: input.actorSubjectId,
|
|
327
335
|
targetSubjectId: input.targetSubjectId,
|
|
328
|
-
operationId: crypto.randomUUID(),
|
|
336
|
+
operationId: input.operationId ?? crypto.randomUUID(),
|
|
329
337
|
};
|
|
330
338
|
return await db.transaction(async (tx) => {
|
|
331
339
|
const txDb = tx as unknown as Database;
|
|
@@ -409,6 +417,201 @@ export async function removeWorkspaceMember(
|
|
|
409
417
|
});
|
|
410
418
|
}
|
|
411
419
|
|
|
420
|
+
type OrganizationWorkspaceCommandResult = {
|
|
421
|
+
workspaceId: string;
|
|
422
|
+
organizationMembershipId?: string;
|
|
423
|
+
workspaceMembershipId?: string;
|
|
424
|
+
updatedAt: string;
|
|
425
|
+
replay: boolean;
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
async function runOrganizationWorkspaceCommand(
|
|
429
|
+
db: Database,
|
|
430
|
+
command: Record<string, unknown> & {
|
|
431
|
+
organizationId: string;
|
|
432
|
+
actorSubjectId: string;
|
|
433
|
+
},
|
|
434
|
+
): Promise<OrganizationWorkspaceCommandResult> {
|
|
435
|
+
return await withRlsContext(
|
|
436
|
+
db,
|
|
437
|
+
{ accountId: command.organizationId, workspaceId: null },
|
|
438
|
+
async (scopedDb) => {
|
|
439
|
+
await setSubjectRlsContext(scopedDb, command.actorSubjectId);
|
|
440
|
+
const [row] = await rawRows<{ result: OrganizationWorkspaceCommandResult }>(
|
|
441
|
+
scopedDb,
|
|
442
|
+
sql`select organization_workspace_command(${JSON.stringify(command)}::jsonb) as result`,
|
|
443
|
+
);
|
|
444
|
+
if (!row) throw new Error("Organization workspace command returned no result");
|
|
445
|
+
return row.result;
|
|
446
|
+
},
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export async function createOrganizationWorkspace(
|
|
451
|
+
db: Database,
|
|
452
|
+
input: {
|
|
453
|
+
organizationId: string;
|
|
454
|
+
actorSubjectId: string;
|
|
455
|
+
name: string;
|
|
456
|
+
operationId: string;
|
|
457
|
+
},
|
|
458
|
+
): Promise<OrganizationWorkspaceAccessType> {
|
|
459
|
+
const command = await runOrganizationWorkspaceCommand(db, { action: "create", ...input });
|
|
460
|
+
const overview = await getOrganizationAdministrationOverview(db, input);
|
|
461
|
+
const workspace = overview.workspaces.find((candidate) => candidate.id === command.workspaceId);
|
|
462
|
+
if (!workspace) throw new Error("Created organization workspace is missing from its overview");
|
|
463
|
+
return OrganizationWorkspaceAccess.parse(workspace);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
export async function updateOrganizationWorkspace(
|
|
467
|
+
db: Database,
|
|
468
|
+
input: {
|
|
469
|
+
organizationId: string;
|
|
470
|
+
actorSubjectId: string;
|
|
471
|
+
workspaceId: string;
|
|
472
|
+
name: string;
|
|
473
|
+
expectedUpdatedAt: string;
|
|
474
|
+
operationId: string;
|
|
475
|
+
},
|
|
476
|
+
): Promise<OrganizationWorkspaceAccessType> {
|
|
477
|
+
await runOrganizationWorkspaceCommand(db, { action: "rename", ...input });
|
|
478
|
+
const overview = await getOrganizationAdministrationOverview(db, input);
|
|
479
|
+
const workspace = overview.workspaces.find((candidate) => candidate.id === input.workspaceId);
|
|
480
|
+
if (!workspace) throw new Error("Renamed organization workspace is missing from its overview");
|
|
481
|
+
return OrganizationWorkspaceAccess.parse(workspace);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
export async function putOrganizationWorkspaceMember(
|
|
485
|
+
db: Database,
|
|
486
|
+
input: {
|
|
487
|
+
organizationId: string;
|
|
488
|
+
actorSubjectId: string;
|
|
489
|
+
workspaceId: string;
|
|
490
|
+
targetOrganizationMembershipId: string;
|
|
491
|
+
access: PutOrganizationWorkspaceMemberRequest;
|
|
492
|
+
},
|
|
493
|
+
) {
|
|
494
|
+
const result = await runOrganizationWorkspaceCommand(db, {
|
|
495
|
+
action: "grant",
|
|
496
|
+
organizationId: input.organizationId,
|
|
497
|
+
actorSubjectId: input.actorSubjectId,
|
|
498
|
+
workspaceId: input.workspaceId,
|
|
499
|
+
targetOrganizationMembershipId: input.targetOrganizationMembershipId,
|
|
500
|
+
...input.access,
|
|
501
|
+
});
|
|
502
|
+
const overview = await getOrganizationAdministrationOverview(db, input);
|
|
503
|
+
const member = overview.workspaces
|
|
504
|
+
.find((candidate) => candidate.id === input.workspaceId)
|
|
505
|
+
?.members.find((candidate) => candidate.membershipId === result.workspaceMembershipId);
|
|
506
|
+
if (!member) throw new Error("Organization workspace member is missing from its overview");
|
|
507
|
+
return member;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Revoke one managed human's shared-workspace access. The existing fenced
|
|
512
|
+
* prepare/settle/removal protocol remains the teardown authority. This outer
|
|
513
|
+
* transaction enters the canonical organization -> session-tenancy ->
|
|
514
|
+
* personal-state prefix before any row lock, then adds caller-owned
|
|
515
|
+
* idempotency, CAS, and immutable organization audit evidence.
|
|
516
|
+
*/
|
|
517
|
+
export async function revokeOrganizationWorkspaceMember(
|
|
518
|
+
db: Database,
|
|
519
|
+
input: {
|
|
520
|
+
organizationId: string;
|
|
521
|
+
actorSubjectId: string;
|
|
522
|
+
workspaceId: string;
|
|
523
|
+
targetOrganizationMembershipId: string;
|
|
524
|
+
expectedUpdatedAt: string;
|
|
525
|
+
operationId: string;
|
|
526
|
+
},
|
|
527
|
+
): Promise<RevokeOrganizationWorkspaceMemberResponseType> {
|
|
528
|
+
return await db.transaction(async (tx) => {
|
|
529
|
+
const txDb = tx as unknown as Database;
|
|
530
|
+
await txDb.execute(
|
|
531
|
+
sql`select pg_advisory_xact_lock(hashtextextended(
|
|
532
|
+
${`organization-membership:${input.organizationId}`}, 0
|
|
533
|
+
))`,
|
|
534
|
+
);
|
|
535
|
+
const targetSubjectId = await withRlsContext(
|
|
536
|
+
txDb,
|
|
537
|
+
{ accountId: input.organizationId, workspaceId: null },
|
|
538
|
+
async (scopedDb) => {
|
|
539
|
+
await setSubjectRlsContext(scopedDb, input.actorSubjectId);
|
|
540
|
+
const [row] = await rawRows<{ subject_id: string }>(
|
|
541
|
+
scopedDb,
|
|
542
|
+
sql`select resolve_organization_workspace_removal_subject(
|
|
543
|
+
${input.organizationId}::uuid,
|
|
544
|
+
${input.actorSubjectId},
|
|
545
|
+
${input.targetOrganizationMembershipId}::uuid
|
|
546
|
+
) as subject_id`,
|
|
547
|
+
);
|
|
548
|
+
if (!row?.subject_id) throw new Error("Organization member subject resolution failed");
|
|
549
|
+
return row.subject_id;
|
|
550
|
+
},
|
|
551
|
+
);
|
|
552
|
+
await txDb.execute(
|
|
553
|
+
sql`select pg_advisory_xact_lock_shared(hashtextextended(
|
|
554
|
+
${`session-tenancy:${input.workspaceId}`}, 0
|
|
555
|
+
))`,
|
|
556
|
+
);
|
|
557
|
+
await txDb.execute(
|
|
558
|
+
sql`select pg_advisory_xact_lock(hashtextextended(
|
|
559
|
+
${`session-personal-state:${input.workspaceId}:${targetSubjectId}`}, 0
|
|
560
|
+
))`,
|
|
561
|
+
);
|
|
562
|
+
const command = { action: "revoke", ...input, targetSubjectId };
|
|
563
|
+
const prepared = await withRlsContext(
|
|
564
|
+
txDb,
|
|
565
|
+
{ accountId: input.organizationId, workspaceId: null },
|
|
566
|
+
async (scopedDb) => {
|
|
567
|
+
await setSubjectRlsContext(scopedDb, input.actorSubjectId);
|
|
568
|
+
const [row] = await rawRows<{ result: Record<string, unknown> }>(
|
|
569
|
+
scopedDb,
|
|
570
|
+
sql`select prepare_organization_workspace_member_removal(
|
|
571
|
+
${JSON.stringify(command)}::jsonb
|
|
572
|
+
) as result`,
|
|
573
|
+
);
|
|
574
|
+
if (!row) throw new Error("Organization workspace removal preparation returned no result");
|
|
575
|
+
return row.result;
|
|
576
|
+
},
|
|
577
|
+
);
|
|
578
|
+
if (prepared.replay === true) {
|
|
579
|
+
return RevokeOrganizationWorkspaceMemberResponse.parse(prepared);
|
|
580
|
+
}
|
|
581
|
+
const workspaceMembershipId = String(prepared.workspaceMembershipId ?? "");
|
|
582
|
+
const actorMembershipId = String(prepared.actorMembershipId ?? "");
|
|
583
|
+
if (!uuidPattern.test(workspaceMembershipId) || !uuidPattern.test(actorMembershipId)) {
|
|
584
|
+
throw new Error("Organization workspace removal preparation returned invalid evidence");
|
|
585
|
+
}
|
|
586
|
+
const removed = await removeWorkspaceMember(txDb, {
|
|
587
|
+
accountId: input.organizationId,
|
|
588
|
+
workspaceId: input.workspaceId,
|
|
589
|
+
actorSubjectId: input.actorSubjectId,
|
|
590
|
+
targetSubjectId,
|
|
591
|
+
requireOrganizationSharedWorkspaceAdministration: true,
|
|
592
|
+
operationId: input.operationId,
|
|
593
|
+
});
|
|
594
|
+
if (!removed) throw new Error("Organization workspace removal lost its locked membership");
|
|
595
|
+
return await withRlsContext(
|
|
596
|
+
txDb,
|
|
597
|
+
{ accountId: input.organizationId, workspaceId: null },
|
|
598
|
+
async (scopedDb) => {
|
|
599
|
+
await setSubjectRlsContext(scopedDb, input.actorSubjectId);
|
|
600
|
+
const [row] = await rawRows<{ result: unknown }>(
|
|
601
|
+
scopedDb,
|
|
602
|
+
sql`select record_organization_workspace_member_removal(
|
|
603
|
+
${JSON.stringify(command)}::jsonb,
|
|
604
|
+
${workspaceMembershipId}::uuid,
|
|
605
|
+
${actorMembershipId}::uuid
|
|
606
|
+
) as result`,
|
|
607
|
+
);
|
|
608
|
+
if (!row) throw new Error("Organization workspace removal audit returned no result");
|
|
609
|
+
return RevokeOrganizationWorkspaceMemberResponse.parse(row.result);
|
|
610
|
+
},
|
|
611
|
+
);
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
|
|
412
615
|
export async function assertActiveManagedHumanOrganizationMembership(
|
|
413
616
|
db: Database,
|
|
414
617
|
input: { accountId: string; subjectId: string },
|
|
@@ -530,6 +733,29 @@ export async function listOrganizationMembers(
|
|
|
530
733
|
);
|
|
531
734
|
}
|
|
532
735
|
|
|
736
|
+
export async function listOrganizationAdministrationMembers(
|
|
737
|
+
db: Database,
|
|
738
|
+
input: { organizationId: string; actorSubjectId: string },
|
|
739
|
+
): Promise<OrganizationAdministrationMemberType[]> {
|
|
740
|
+
return await withRlsContext(
|
|
741
|
+
db,
|
|
742
|
+
{ accountId: input.organizationId, workspaceId: null },
|
|
743
|
+
async (scopedDb) => {
|
|
744
|
+
await setSubjectRlsContext(scopedDb, input.actorSubjectId);
|
|
745
|
+
const [row] = await rawRows<{ result: unknown }>(
|
|
746
|
+
scopedDb,
|
|
747
|
+
sql`select list_organization_administration_members(
|
|
748
|
+
${input.organizationId}::uuid,
|
|
749
|
+
${input.actorSubjectId}
|
|
750
|
+
) as result`,
|
|
751
|
+
);
|
|
752
|
+
return ListOrganizationAdministrationMembersResponse.parse({
|
|
753
|
+
members: row?.result ?? [],
|
|
754
|
+
}).members;
|
|
755
|
+
},
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
|
|
533
759
|
export async function getOrganizationAdministrationOverview(
|
|
534
760
|
db: Database,
|
|
535
761
|
input: { organizationId: string; actorSubjectId: string },
|
|
@@ -671,6 +897,32 @@ export async function listOrganizationInvitations(
|
|
|
671
897
|
);
|
|
672
898
|
}
|
|
673
899
|
|
|
900
|
+
export async function getOrganizationInvitationForAdministration(
|
|
901
|
+
db: Database,
|
|
902
|
+
input: {
|
|
903
|
+
organizationId: string;
|
|
904
|
+
actorSubjectId: string;
|
|
905
|
+
invitationId: string;
|
|
906
|
+
},
|
|
907
|
+
): Promise<OrganizationInvitationType> {
|
|
908
|
+
return await withRlsContext(
|
|
909
|
+
db,
|
|
910
|
+
{ accountId: input.organizationId, workspaceId: null },
|
|
911
|
+
async (scopedDb) => {
|
|
912
|
+
await setSubjectRlsContext(scopedDb, input.actorSubjectId);
|
|
913
|
+
const [row] = await rawRows<{ result: unknown }>(
|
|
914
|
+
scopedDb,
|
|
915
|
+
sql`select get_organization_invitation_for_administration(
|
|
916
|
+
${input.organizationId}::uuid,
|
|
917
|
+
${input.actorSubjectId},
|
|
918
|
+
${input.invitationId}::uuid
|
|
919
|
+
) as result`,
|
|
920
|
+
);
|
|
921
|
+
return OrganizationInvitation.parse(row?.result);
|
|
922
|
+
},
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
|
|
674
926
|
export async function createOrganizationInvitation(
|
|
675
927
|
db: Database,
|
|
676
928
|
input: CommandBase & {
|