Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions libs/prisma-service/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ model oidc_issuer {
orgId String? @db.Uuid
isPrimary Boolean @default(false)

organisation organisation? @relation(fields: [orgId], references: [id])
organisation organisation? @relation(fields: [orgId], references: [id], onDelete: SetNull)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Application-level deletion guard is now inconsistent with the declared onDelete: SetNull behavior

Prisma's implicit default onDelete for optional relations is already SetNull, so making this explicit is the correct fix for the migration failure. However, a behavioral inconsistency has been introduced across the codebase.

deleteOrganisation in apps/organization/repositories/organization.repository.ts (lines 860–876):

  • Pre-checks record counts in oidc_issuer, oid4vc_credentials, and issued_oid4vc_credentials
  • Throws ConflictException if any rows reference the org — preventing deletion entirely for these three tables

Compare this with how schema and credential_definition are handled: both declare onDelete: SetNull and the same deleteOrganisation method explicitly calls updateMany({ data: { orgId: null } }) before the delete, keeping the DB-level action and application logic aligned.

For the three models in this PR, the contract is contradictory:

  • DB level: deletion of organisation rows sets orgId to null via the FK cascade
  • App level: deletion is blocked with a 409 Conflict if any such rows exist

In practice this means onDelete: SetNull never fires for app-initiated deletes (the guard prevents reaching prisma.organisation.delete), but will fire for any direct DB-level deletion (migrations with cascades, admin tooling, raw SQL). If that happens, getCredentialAllocations in apps/oid4vc-issuance/src/status-list-allocator.service.ts queries { where: { orgId, issuanceSessionId } } and would silently return no results for any credential whose orgId was nulled out.

The fix should align the two layers — either:

  1. Preferred (consistent with schema/credential_definition): Update deleteOrganisation to null out orgId in these three tables instead of throwing, relying on the DB-level SetNull cascade.
  2. Alternative: Keep the ConflictException and change the referential action to onDelete: Restrict (verify that this doesn't re-introduce the migration failure).

Also applies to: 623-623, 670-670

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/prisma-service/prisma/schema.prisma` at line 603, The DB schema uses
onDelete: SetNull for the organisation FK but deleteOrganisation in
apps/organization/repositories/organization.repository.ts currently throws
ConflictException when oidc_issuer, oid4vc_credentials, or
issued_oid4vc_credentials reference the org, creating a behavioral mismatch;
update deleteOrganisation to mirror how schema and credential_definition are
handled by calling updateMany on the three models (oidc_issuer,
oid4vc_credentials, issued_oid4vc_credentials) to set orgId: null for rows with
the target org id before invoking prisma.organisation.delete, so the
application-level logic aligns with the declared onDelete: SetNull behavior.


@@index([orgAgentId])
}
Expand All @@ -620,8 +620,8 @@ model oid4vc_credentials {
issuedCredentials String[]
publicIssuerId String

organisation organisation? @relation(fields: [orgId], references: [id])

organisation organisation? @relation(fields: [orgId], references: [id], onDelete: SetNull)
@@index([credentialConfigurationIds], type: Gin)
}

Expand Down Expand Up @@ -667,7 +667,7 @@ model issued_oid4vc_credentials {
updatedAt DateTime @updatedAt
statusListUri String

organisation organisation? @relation(fields: [orgId], references: [id])
organisation organisation? @relation(fields: [orgId], references: [id], onDelete: SetNull)

@@index([orgId, issuanceSessionId])
}
Expand Down
Loading