diff --git a/sql/023_canonical_grants.sql b/sql/023_canonical_grants.sql index 8fe96b2..fb5dd0e 100644 --- a/sql/023_canonical_grants.sql +++ b/sql/023_canonical_grants.sql @@ -13,7 +13,7 @@ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '0pt_app') THEN GRANT SELECT, INSERT, UPDATE, DELETE ON opt_canonical_entities, opt_canonical_facts, opt_canonical_relations - TO 0pt_app; + TO "0pt_app"; END IF; END $$; diff --git a/src/repositories/canonical-fact-repository.ts b/src/repositories/canonical-fact-repository.ts index 4e22ed7..3c13a7a 100644 --- a/src/repositories/canonical-fact-repository.ts +++ b/src/repositories/canonical-fact-repository.ts @@ -30,6 +30,11 @@ export interface CanonicalFactRepository { queryFacts(query: CanonicalQuery): Promise; } +/** PostgreSQL timestamptz arrives as Date; the API contract is RFC3339/ISO-8601. */ +function iso(value: unknown): string { + return value instanceof Date ? value.toISOString() : String(value); +} + export function entityKey(e: CanonicalEntityInput): string { return `${e.entity_type}\u0000${e.identity_namespace}\u0000${e.identity_value}`; } @@ -216,11 +221,11 @@ class PostgresCanonicalFactRepository implements CanonicalFactRepository { source_record_id: r.source_record_id ?? undefined, st0re_artifact_id: r.st0re_artifact_id ?? undefined, aud0_evidence_ref: r.aud0_evidence_ref ?? undefined, run_ref: r.run_ref ?? undefined, - extractor_version: r.extractor_version, observed_at: String(r.observed_at), - valid_from: r.valid_from ? String(r.valid_from) : undefined, - valid_to: r.valid_to ? String(r.valid_to) : undefined, + extractor_version: r.extractor_version, observed_at: iso(r.observed_at), + valid_from: r.valid_from ? iso(r.valid_from) : undefined, + valid_to: r.valid_to ? iso(r.valid_to) : undefined, confidence: r.confidence === null ? undefined : Number(r.confidence), - quality_status: r.quality_status, status: r.status, created_at: String(r.created_at), + quality_status: r.quality_status, status: r.status, created_at: iso(r.created_at), })) as CanonicalFact[]; }); }