Fix/vat parent accounts (#438)
* feat(enable-banking): add support for account selection and syncing - Updated StoredAccount interface to include an 'enabled' flag for account syncing preferences. - Enhanced ensureFiscalPeriod function to handle overlapping fiscal periods with posted entries and opening balances. - Added tests for fiscal period validation and account syncing logic. - Implemented AccountPickerDialog component for user account selection. - Created API routes for PATCH /accounts and POST /sync to manage account syncing. - Introduced 'pending_selection' status for bank connections to allow user account selection before syncing. - Updated database migration to support new connection status and backfill existing accounts with enabled=true. * feat(enable-banking): implement account selection and consent event logging --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
d0fbc2b616
commit
a53a119a2e
@@ -39,6 +39,11 @@ const PERSISTED_EVENT_TYPES: CoreEventType[] = [
|
||||
'mcp.tool_called',
|
||||
'mcp.tools_list_called',
|
||||
'mcp.resource_read',
|
||||
// Bank connection consent lifecycle — required audit trail per ASVS V16
|
||||
// and GDPR Art.30 (records of processing) for PSD2 consent decisions.
|
||||
'bank_connection.consent_granted',
|
||||
'bank_connection.account_selection_changed',
|
||||
'bank_connection.revoked',
|
||||
]
|
||||
|
||||
// Excluded (with reasoning):
|
||||
@@ -65,6 +70,13 @@ function extractEntityId(payload: Record<string, unknown>): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
// Flat-string ID fields on events that don't carry a full entity object.
|
||||
// Bank connection events fall into this category — the connection lives in
|
||||
// an extension table, so we record its id directly.
|
||||
if (typeof payload.connectionId === 'string') {
|
||||
return payload.connectionId
|
||||
}
|
||||
|
||||
// For journal_entry.corrected: use the corrected entry's ID
|
||||
if ('corrected' in payload) {
|
||||
const corrected = payload.corrected
|
||||
|
||||
@@ -35,6 +35,11 @@ export type CoreEvent =
|
||||
| { type: 'transaction.synced'; payload: { transactions: Transaction[]; userId: string; companyId: string } }
|
||||
| { type: 'transaction.categorized'; payload: { transaction: Transaction; account: string; taxCode: string; userId: string; companyId: string } }
|
||||
| { type: 'transaction.reconciled'; payload: { transaction: Transaction; journalEntryId: string; method: ReconciliationMethod; userId: string; companyId: string } }
|
||||
// Bank connection lifecycle — consent + account selection are the
|
||||
// GDPR/PSD2 audit points; emitted to event_log for compliance trail.
|
||||
| { type: 'bank_connection.consent_granted'; payload: { connectionId: string; bankName: string | null; accountCount: number; consentExpiresAt: string | null; userId: string; companyId: string } }
|
||||
| { type: 'bank_connection.account_selection_changed'; payload: { connectionId: string; bankName: string | null; previousStatus: string; newStatus: string; enabledCount: number; totalCount: number; userId: string; companyId: string } }
|
||||
| { type: 'bank_connection.revoked'; payload: { connectionId: string; bankName: string | null; userId: string; companyId: string } }
|
||||
// Periods
|
||||
| { type: 'period.locked'; payload: { period: FiscalPeriod; userId: string; companyId: string } }
|
||||
| { type: 'period.unlocked'; payload: { period: FiscalPeriod; userId: string; companyId: string } }
|
||||
|
||||
Reference in New Issue
Block a user