feat(federation): grants service CRUD + status transitions (FED-M2-06)
- Add 'pending' to grantStatusEnum (pending → active → revoked/expired) - Update federationGrants default status to 'pending' - Add migration 0009_federation_grant_pending.sql - GrantsService: createGrant, getGrant, listGrants, activateGrant, revokeGrant, expireGrant - Invalid transitions throw ConflictException; missing grants throw NotFoundException - CreateGrantDto validates scope via parseFederationScope before insert - Full unit test coverage for all status transitions and edge cases Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2
packages/db/drizzle/0009_federation_grant_pending.sql
Normal file
2
packages/db/drizzle/0009_federation_grant_pending.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TYPE "public"."grant_status" ADD VALUE 'pending' BEFORE 'active';--> statement-breakpoint
|
||||
ALTER TABLE "federation_grants" ALTER COLUMN "status" SET DEFAULT 'pending';
|
||||
3376
packages/db/drizzle/meta/0009_snapshot.json
Normal file
3376
packages/db/drizzle/meta/0009_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -64,6 +64,13 @@
|
||||
"when": 1776822435828,
|
||||
"tag": "0008_smart_lyja",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"version": "7",
|
||||
"when": 1745280000000,
|
||||
"tag": "0009_federation_grant_pending",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -604,11 +604,12 @@ export const peerStateEnum = pgEnum('peer_state', ['pending', 'active', 'suspend
|
||||
|
||||
/**
|
||||
* Lifecycle state of a federation grant.
|
||||
* - pending: created but not yet activated (awaiting cert enrollment, M2-07)
|
||||
* - active: grant is in effect
|
||||
* - revoked: manually revoked before expiry
|
||||
* - expired: natural expiry (expires_at passed)
|
||||
*/
|
||||
export const grantStatusEnum = pgEnum('grant_status', ['active', 'revoked', 'expired']);
|
||||
export const grantStatusEnum = pgEnum('grant_status', ['pending', 'active', 'revoked', 'expired']);
|
||||
|
||||
/**
|
||||
* A registered peer gateway identified by its Step-CA certificate CN.
|
||||
@@ -696,7 +697,7 @@ export const federationGrants = pgTable(
|
||||
scope: jsonb('scope').notNull(),
|
||||
|
||||
/** Current grant lifecycle state. */
|
||||
status: grantStatusEnum('status').notNull().default('active'),
|
||||
status: grantStatusEnum('status').notNull().default('pending'),
|
||||
|
||||
/** Optional hard expiry. NULL means the grant does not expire automatically. */
|
||||
expiresAt: timestamp('expires_at', { withTimezone: true }),
|
||||
|
||||
Reference in New Issue
Block a user