forked from bai/curriculum-project-hub
feat: secure organization Feishu credentials
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
-- ADR-0024: one Organization-scoped customer Feishu application connection
|
||||
-- with immutable encrypted credential versions. No Feishu plaintext column is
|
||||
-- present in either table.
|
||||
|
||||
CREATE TABLE "OrganizationFeishuApplicationConnection" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organizationId" TEXT NOT NULL,
|
||||
"appIdentityFingerprint" TEXT NOT NULL,
|
||||
"status" "OrganizationConnectionStatus" NOT NULL DEFAULT 'DRAFT',
|
||||
"activeSecretVersionId" TEXT,
|
||||
"activatedAt" TIMESTAMP(3),
|
||||
"disabledAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "OrganizationFeishuApplicationConnection_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "FeishuApplicationCredentialVersion" (
|
||||
"id" TEXT NOT NULL,
|
||||
"connectionId" TEXT NOT NULL,
|
||||
"version" INTEGER NOT NULL,
|
||||
"envelopeVersion" INTEGER NOT NULL DEFAULT 1,
|
||||
"keyId" TEXT NOT NULL,
|
||||
"envelope" JSONB NOT NULL,
|
||||
"createdByUserId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"retiredAt" TIMESTAMP(3),
|
||||
CONSTRAINT "FeishuApplicationCredentialVersion_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "OrganizationFeishuApplicationConnection_organizationId_key"
|
||||
ON "OrganizationFeishuApplicationConnection"("organizationId");
|
||||
CREATE UNIQUE INDEX "OrganizationFeishuApplicationConnection_appIdentityFingerprint_key"
|
||||
ON "OrganizationFeishuApplicationConnection"("appIdentityFingerprint");
|
||||
CREATE UNIQUE INDEX "OrganizationFeishuApplicationConnection_activeSecretVersionId_key"
|
||||
ON "OrganizationFeishuApplicationConnection"("activeSecretVersionId");
|
||||
CREATE INDEX "OrganizationFeishuApplicationConnection_status_idx"
|
||||
ON "OrganizationFeishuApplicationConnection"("status");
|
||||
CREATE UNIQUE INDEX "FeishuApplicationCredentialVersion_connectionId_version_key"
|
||||
ON "FeishuApplicationCredentialVersion"("connectionId", "version");
|
||||
CREATE INDEX "FeishuApplicationCredentialVersion_connectionId_retiredAt_idx"
|
||||
ON "FeishuApplicationCredentialVersion"("connectionId", "retiredAt");
|
||||
CREATE INDEX "FeishuApplicationCredentialVersion_keyId_idx"
|
||||
ON "FeishuApplicationCredentialVersion"("keyId");
|
||||
CREATE INDEX "FeishuApplicationCredentialVersion_createdByUserId_idx"
|
||||
ON "FeishuApplicationCredentialVersion"("createdByUserId");
|
||||
|
||||
ALTER TABLE "OrganizationFeishuApplicationConnection"
|
||||
ADD CONSTRAINT "OrganizationFeishuApplicationConnection_organizationId_fkey"
|
||||
FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
ALTER TABLE "FeishuApplicationCredentialVersion"
|
||||
ADD CONSTRAINT "FeishuApplicationCredentialVersion_connectionId_fkey"
|
||||
FOREIGN KEY ("connectionId") REFERENCES "OrganizationFeishuApplicationConnection"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
ALTER TABLE "FeishuApplicationCredentialVersion"
|
||||
ADD CONSTRAINT "FeishuApplicationCredentialVersion_createdByUserId_fkey"
|
||||
FOREIGN KEY ("createdByUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE "OrganizationFeishuApplicationConnection"
|
||||
ADD CONSTRAINT "OrganizationFeishuApplicationConnection_activeSecretVersionId_fkey"
|
||||
FOREIGN KEY ("activeSecretVersionId") REFERENCES "FeishuApplicationCredentialVersion"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -42,6 +42,7 @@ model Organization {
|
||||
teams Team[]
|
||||
externalDirectoryConnections ExternalDirectoryConnection[]
|
||||
providerConnections OrganizationProviderConnection[]
|
||||
feishuApplicationConnection OrganizationFeishuApplicationConnection?
|
||||
auditEntries AuditEntry[] @relation("organizationAudit")
|
||||
|
||||
@@index([status])
|
||||
@@ -109,6 +110,51 @@ model User {
|
||||
roleTriggerGrants RoleTriggerGrant[] @relation("roleGrantCreator")
|
||||
auditEntries AuditEntry[] @relation("auditActor")
|
||||
providerCredentialVersions ProviderCredentialVersion[] @relation("providerCredentialVersionCreator")
|
||||
feishuCredentialVersions FeishuApplicationCredentialVersion[] @relation("feishuCredentialVersionCreator")
|
||||
}
|
||||
|
||||
/// ADR-0024: exactly one customer-owned Feishu application connection may be
|
||||
/// configured for an Organization. External Feishu identifiers are scoped by
|
||||
/// this stable connection id, never treated as process-global identities.
|
||||
model OrganizationFeishuApplicationConnection {
|
||||
id String @id @default(cuid())
|
||||
organizationId String @unique
|
||||
appIdentityFingerprint String @unique
|
||||
status OrganizationConnectionStatus @default(DRAFT)
|
||||
activeSecretVersionId String? @unique
|
||||
activatedAt DateTime?
|
||||
disabledAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
secretVersions FeishuApplicationCredentialVersion[] @relation("feishuCredentialVersions")
|
||||
activeSecretVersion FeishuApplicationCredentialVersion? @relation("activeFeishuCredentialVersion", fields: [activeSecretVersionId], references: [id], onDelete: Restrict)
|
||||
|
||||
@@index([status])
|
||||
}
|
||||
|
||||
/// ADR-0024: all Feishu app material, including provider-local app/bot ids, is
|
||||
/// inside one immutable authenticated envelope version.
|
||||
model FeishuApplicationCredentialVersion {
|
||||
id String @id @default(cuid())
|
||||
connectionId String
|
||||
version Int
|
||||
envelopeVersion Int @default(1)
|
||||
keyId String
|
||||
envelope Json
|
||||
createdByUserId String?
|
||||
createdAt DateTime @default(now())
|
||||
retiredAt DateTime?
|
||||
|
||||
connection OrganizationFeishuApplicationConnection @relation("feishuCredentialVersions", fields: [connectionId], references: [id], onDelete: Cascade)
|
||||
activeFor OrganizationFeishuApplicationConnection? @relation("activeFeishuCredentialVersion")
|
||||
createdBy User? @relation("feishuCredentialVersionCreator", fields: [createdByUserId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@unique([connectionId, version])
|
||||
@@index([connectionId, retiredAt])
|
||||
@@index([keyId])
|
||||
@@index([createdByUserId])
|
||||
}
|
||||
|
||||
/// ADR-0024: model-provider connection identity is stable and belongs to one
|
||||
|
||||
Reference in New Issue
Block a user