feat(24-01): install AWS Route 53 SDK and create dedicated schema migration

- Add @aws-sdk/client-route-53 dependency (official aws-sdk-js-v3 package)
- Add migrations/102_route53_tables.sql: route53_zones, route53_records,
  route53_record_history (D-06 change ledger), route53_audit_log
  (D-03/D-07 attempt audit log with pending/committed/failed status)
- Seed integration_settings row for key='route53' (D-10, display-only toggle)
- Unbounded retention by design (D-08) — no purge job, no TTL, no DELETE
This commit is contained in:
lorentz 2026-08-05 19:23:43 -04:00
parent 602c3bb7b5
commit b9df27b656
3 changed files with 478 additions and 95 deletions

View file

@ -0,0 +1,149 @@
-- AWS Route 53 DNS sync — Phase 24 dedicated Postgres schema.
--
-- Lays down the full Route 53 schema this phase's downstream plans (sync
-- service, CRUD routes, health check, admin UI) will populate and consume.
--
-- • Hosted zones (mirror of AWS Route 53 zones) -> route53_zones
-- • Resource record sets (mirror of AWS records) -> route53_records
-- • Append-only change ledger (drift + CRUD) -> route53_record_history
-- • Append-only attempt audit log (D-03/D-07) -> route53_audit_log
--
-- Retention is unbounded by design (D-08) — no purge job, no TTL, and no
-- DELETE statement against route53_record_history or route53_audit_log
-- anywhere in this phase, matching existing Pulse convention (itglue_writes,
-- itglue_asset_audits, phishing audit_events are all forever-retained too).
-- ---------------------------------------------------------------------------
-- 1. route53_zones — mirror of AWS Route 53 hosted zones
-- ---------------------------------------------------------------------------
-- id is the AWS hosted zone id with the '/hostedzone/' prefix stripped — the
-- natural stable identifier Route 53 already provides, no synthetic UUID
-- needed. authoritative_name_servers backs the D-12 NS-delegation health
-- check planned in 24-04.
CREATE TABLE IF NOT EXISTS route53_zones (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
comment TEXT,
private_zone BOOLEAN NOT NULL DEFAULT false,
record_count INTEGER NOT NULL DEFAULT 0,
authoritative_name_servers JSONB,
raw_payload JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
is_deleted BOOLEAN NOT NULL DEFAULT false,
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_route53_zones_is_deleted ON route53_zones(is_deleted);
CREATE INDEX IF NOT EXISTS idx_route53_zones_name ON route53_zones(name);
-- ---------------------------------------------------------------------------
-- 2. route53_records — mirror of AWS Route 53 resource record sets
-- ---------------------------------------------------------------------------
-- record_key is the composite string `zoneId:name:type:setIdentifier` (empty
-- string when there is no set identifier) — Route 53 recordsets are uniquely
-- identified by zone+name+type+SetIdentifier; there is no AWS-side record id
-- to use as a natural primary key.
CREATE TABLE IF NOT EXISTS route53_records (
record_key TEXT PRIMARY KEY,
zone_id TEXT NOT NULL REFERENCES route53_zones(id) ON DELETE CASCADE,
name TEXT NOT NULL,
type TEXT NOT NULL,
set_identifier TEXT,
ttl INTEGER,
resource_records JSONB,
alias_target JSONB,
raw_payload JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
is_deleted BOOLEAN NOT NULL DEFAULT false,
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_route53_records_zone ON route53_records(zone_id);
CREATE INDEX IF NOT EXISTS idx_route53_records_is_deleted ON route53_records(is_deleted);
CREATE INDEX IF NOT EXISTS idx_route53_records_name_type ON route53_records(zone_id, name, type);
-- ---------------------------------------------------------------------------
-- 3. route53_record_history — append-only change ledger (D-06)
-- ---------------------------------------------------------------------------
-- Written by BOTH the sync service (source='sync_detected_drift', when a
-- previously-synced record's live AWS value no longer matches Postgres) and
-- the CRUD routes (source='pulse_crud', on every successful write). Distinct
-- from route53_audit_log below: this table is a per-record timeline of
-- resolved changes; the audit log below is a per-attempt ledger including
-- failures. audit_log_id is a soft (non-FK) reference so a history row
-- survives independent of the audit log's own lifecycle.
CREATE TABLE IF NOT EXISTS route53_record_history (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
zone_id TEXT NOT NULL REFERENCES route53_zones(id) ON DELETE CASCADE,
record_key TEXT NOT NULL,
record_name TEXT NOT NULL,
record_type TEXT NOT NULL,
change_action TEXT NOT NULL CHECK (change_action IN ('create','update','delete')),
before_value JSONB,
after_value JSONB,
source TEXT NOT NULL CHECK (source IN ('pulse_crud','sync_detected_drift')),
changed_by_user_id TEXT REFERENCES "user"(id) ON DELETE SET NULL,
changed_by_email TEXT,
audit_log_id UUID, -- soft ref -> route53_audit_log(id), no hard FK
changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_route53_record_history_record ON route53_record_history(record_key, changed_at DESC);
CREATE INDEX IF NOT EXISTS idx_route53_record_history_source ON route53_record_history(source);
CREATE INDEX IF NOT EXISTS idx_route53_record_history_zone ON route53_record_history(zone_id, changed_at DESC);
-- ---------------------------------------------------------------------------
-- 4. route53_audit_log — append-only attempt audit log (D-03/D-07)
-- ---------------------------------------------------------------------------
-- One row per attempted CRUD/sync operation, including failures. zone_id is
-- deliberately NOT an FK here (unlike route53_record_history above) — a
-- failed attempt against a zone that was never synced must still be
-- recordable. D-03 accepted tradeoff: destructive record operations execute
-- immediately with no staged approval gate; this table is the compensating
-- post-hoc traceability control (actor, timestamp, before/after for every
-- attempt), not a pre-write block.
CREATE TABLE IF NOT EXISTS route53_audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
operation TEXT NOT NULL CHECK (operation IN ('create','update','delete','sync')),
zone_id TEXT,
record_key TEXT,
record_name TEXT,
record_type TEXT,
before_value JSONB,
after_value JSONB,
performed_by_user_id TEXT REFERENCES "user"(id) ON DELETE SET NULL,
performed_by_email TEXT,
performed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
completed_at TIMESTAMPTZ,
status TEXT NOT NULL CHECK (status IN ('pending','committed','failed')),
aws_change_id TEXT,
aws_change_status TEXT,
aws_response JSONB,
error_message TEXT
);
CREATE INDEX IF NOT EXISTS ix_route53_audit_log_record ON route53_audit_log(zone_id, record_key, performed_at DESC);
CREATE INDEX IF NOT EXISTS ix_route53_audit_log_status ON route53_audit_log(status);
COMMENT ON TABLE route53_record_history IS
'Append-only per-record change timeline. source distinguishes CRUD writes (pulse_crud) from sync-detected drift (sync_detected_drift). Unbounded retention by design (D-08) — no purge job.';
COMMENT ON TABLE route53_audit_log IS
'Append-only per-attempt audit log including failures. D-03 accepted tradeoff: destructive record ops execute immediately with no pre-write approval gate; this table is the post-hoc compensating control. Unbounded retention by design (D-08) — no purge job.';
-- ---------------------------------------------------------------------------
-- 5. integration_settings seed row (D-10)
-- ---------------------------------------------------------------------------
-- Display-only toggle on /admin/integrations — no sync/CRUD-blocking
-- behavior anywhere in this phase (unlike PAX8's disable-gates-fullSync
-- exception). Extends the existing seed list from migrations/081 rather
-- than editing that committed file.
INSERT INTO integration_settings (key, disabled) VALUES ('route53', false) ON CONFLICT (key) DO NOTHING;

423
package-lock.json generated
View file

@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@anthropic-ai/sdk": "^0.91.1",
"@aws-sdk/client-route-53": "^3.1104.0",
"@better-auth/cli": "^1.4.10",
"@hookform/resolvers": "^5.2.2",
"@radix-ui/react-accordion": "^1.2.12",
@ -246,6 +247,279 @@
"node": ">=14.0.0"
}
},
"node_modules/@aws-sdk/client-route-53": {
"version": "3.1104.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-route-53/-/client-route-53-3.1104.0.tgz",
"integrity": "sha512-19Wzq64FbYtZKcN/AoXwq4Nht+HwxTIVNI5QbUzLZ8Dyld0da6xdNIOBxX/0bGu5bnijj4dxJjokvLRoTpOpOA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/credential-provider-node": "^3.972.78",
"@aws-sdk/middleware-sdk-route53": "^3.972.23",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/fetch-http-handler": "^5.6.13",
"@smithy/node-http-handler": "^4.9.13",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/core": {
"version": "3.977.6",
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.977.6.tgz",
"integrity": "sha512-QiaJV4/zDrB4ZY2mfeSXSzSTc36W16sZXcGz+SPFk0CJ26gziO0cS+4LjJUMAbdeeBOvS0k0Aq1cZpfGdUXxSw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "^3.974.2",
"@aws-sdk/xml-builder": "^3.972.37",
"@aws/lambda-invoke-store": "^0.3.0",
"@smithy/core": "^3.31.1",
"@smithy/signature-v4": "^5.6.12",
"@smithy/types": "^4.16.1",
"bowser": "^2.11.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/credential-provider-env": {
"version": "3.972.67",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.67.tgz",
"integrity": "sha512-rcIpk5kxUqDaaNa6Xk23pQ6ViY7jlqzmfFWCahQcBT97ddXaXYYwzCen9Tz1Jvo6aJft6wDl5bN44/Jw5B4oLA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/credential-provider-http": {
"version": "3.972.69",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.69.tgz",
"integrity": "sha512-nggwJtZ4eeNsUw5IeWBMXsi1ryct5idi0K+/SCRF3kybLubOMaNTb3XCihXpWMiVpyzyPeIrl0zTkzhBH9porA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/fetch-http-handler": "^5.6.13",
"@smithy/node-http-handler": "^4.9.13",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/credential-provider-ini": {
"version": "3.973.12",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.12.tgz",
"integrity": "sha512-pNEf/OeyN5X3VmLKlgSO6TqaWmW10CvI3TfwL1XhsuhYjSLT2VDaxFnCPHnOeQXSaFisMX4jNhpETriqN8DOmg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/credential-provider-env": "^3.972.67",
"@aws-sdk/credential-provider-http": "^3.972.69",
"@aws-sdk/credential-provider-login": "^3.972.74",
"@aws-sdk/credential-provider-process": "^3.972.67",
"@aws-sdk/credential-provider-sso": "^3.973.11",
"@aws-sdk/credential-provider-web-identity": "^3.972.73",
"@aws-sdk/nested-clients": "^3.997.41",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/credential-provider-imds": "^4.4.16",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/credential-provider-login": {
"version": "3.972.74",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.74.tgz",
"integrity": "sha512-0AQfDcf99TNmqVKv0owHrw/TQs6i4ZE5t9qmz6NvO53bE/sA/tpXhXL9AAcEP1qHc6Zzjd1UMb69+/9zdhvY3g==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/nested-clients": "^3.997.41",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/credential-provider-node": {
"version": "3.972.78",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.78.tgz",
"integrity": "sha512-OgPAnfvbGAMWac6yvxJ1ihslrvDpPVwR68D2csospdNCCyPvHk9JLzYKwz48SNiS1T2znDwHauywRKRFfpyYng==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/credential-provider-env": "^3.972.67",
"@aws-sdk/credential-provider-http": "^3.972.69",
"@aws-sdk/credential-provider-ini": "^3.973.12",
"@aws-sdk/credential-provider-process": "^3.972.67",
"@aws-sdk/credential-provider-sso": "^3.973.11",
"@aws-sdk/credential-provider-web-identity": "^3.972.73",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/credential-provider-imds": "^4.4.16",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/credential-provider-process": {
"version": "3.972.67",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.67.tgz",
"integrity": "sha512-IlUEejorGTWKb4/Dm7K5Yw4QxUmXLThLhrvBmzVBqZFTbW72cv9LTcITmo1dsnYriALE4h68mOq4LB99x6sQ7Q==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/credential-provider-sso": {
"version": "3.973.11",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.11.tgz",
"integrity": "sha512-gAQBkBZxUB84d71+pPcI9L+jh2ujhuAVxc/4FgGiWFDjkPBlMKxzd5XDtkSXTFX8Ro7ansnT88+XadasxMeCRw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/nested-clients": "^3.997.41",
"@aws-sdk/token-providers": "3.1103.0",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/credential-provider-web-identity": {
"version": "3.972.73",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.73.tgz",
"integrity": "sha512-SnlEmQa6SjOgs6iOPLUQl1Eyq4AKiAdPQlkOhFhqNfDtDCwibMGvL6QlkSmf3o6vAUSImzdPCxowT5dfQUZP1A==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/nested-clients": "^3.997.41",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/nested-clients": {
"version": "3.997.41",
"resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.41.tgz",
"integrity": "sha512-RDHqPGQWlF6tatA/Tp3rg6oIwtgN9IVderxE+9av2Y93Dfyu+mO1hZ5Bu2jpfZg2rwdNbsssnwM+sLafIczMlQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/signature-v4-multi-region": "^3.996.43",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/fetch-http-handler": "^5.6.13",
"@smithy/node-http-handler": "^4.9.13",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/signature-v4-multi-region": {
"version": "3.996.43",
"resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.43.tgz",
"integrity": "sha512-lKekx8bLBXSv4O+cslk9Zfnw2XKSkWBs3uWL5QGhH2ZAQfNS7FE0vcSSN2vD/AhxX54ZTywWxR4STThoeOXlBA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "^3.974.2",
"@smithy/signature-v4": "^5.6.12",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/token-providers": {
"version": "3.1103.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1103.0.tgz",
"integrity": "sha512-N4wy26MNn31ItGVHYHPrEuCIFY4MBBjC+C5v1lJKqIUSA7OZBdhleCY53zCCrXn27hsk7YNOaTuhQu807S4AfQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "^3.977.6",
"@aws-sdk/nested-clients": "^3.997.41",
"@aws-sdk/types": "^3.974.2",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/types": {
"version": "3.974.2",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.2.tgz",
"integrity": "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws-sdk/xml-builder": {
"version": "3.972.37",
"resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.37.tgz",
"integrity": "sha512-zKq4HQum8JwDyEuyfuI4bbiAcU0KxP6qy+9PR/IsR92IyE/DaBAikzAS50tjxip4bqIIANpCcG+Yyj6CVhXupg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/client-route-53/node_modules/@aws/lambda-invoke-store": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.3.0.tgz",
"integrity": "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==",
"license": "Apache-2.0",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@aws-sdk/client-sesv2": {
"version": "3.943.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sesv2/-/client-sesv2-3.943.0.tgz",
@ -587,6 +861,33 @@
"node": ">=18.0.0"
}
},
"node_modules/@aws-sdk/middleware-sdk-route53": {
"version": "3.972.23",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-route53/-/middleware-sdk-route53-3.972.23.tgz",
"integrity": "sha512-p2mbkuh45ZLjaDPiQVHP679Rpj7hcK7zUAy4SBe91xur8jG43OZOyX0M9ScLP5BcqWksX87V+ucyvq8YJ/gIHQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "^3.974.2",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/middleware-sdk-route53/node_modules/@aws-sdk/types": {
"version": "3.974.2",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.2.tgz",
"integrity": "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@aws-sdk/middleware-sdk-s3": {
"version": "3.943.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.943.0.tgz",
@ -5370,20 +5671,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@smithy/abort-controller": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz",
"integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/config-resolver": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz",
@ -5403,21 +5690,12 @@
}
},
"node_modules/@smithy/core": {
"version": "3.18.7",
"resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.7.tgz",
"integrity": "sha512-axG9MvKhMWOhFbvf5y2DuyTxQueO0dkedY9QC3mAfndLosRI/9LJv8WaL0mw7ubNhsO4IuXX9/9dYGPFvHrqlw==",
"dev": true,
"version": "3.31.1",
"resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.31.1.tgz",
"integrity": "sha512-CyogUINxvi7C7LDsh8Syo6hVJOT9ckz4rG8dRZfTJ8r91HkMY59PnNooaj7WcHyxEkxPfBAmbgztZU+xTo76lg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/middleware-serde": "^4.2.6",
"@smithy/protocol-http": "^5.3.5",
"@smithy/types": "^4.9.0",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-body-length-browser": "^4.2.0",
"@smithy/util-middleware": "^4.2.5",
"@smithy/util-stream": "^4.5.6",
"@smithy/util-utf8": "^4.2.0",
"@smithy/uuid": "^1.1.0",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
@ -5425,16 +5703,13 @@
}
},
"node_modules/@smithy/credential-provider-imds": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz",
"integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==",
"dev": true,
"version": "4.4.16",
"resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.16.tgz",
"integrity": "sha512-QfuLWAkLzptffFW980AFeHZFdqds2B64rpEd3uJ6lgs3xVn9QegGMUgUcj+4d7dRrAsya3r58ZKpku97WcFb4w==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/node-config-provider": "^4.3.5",
"@smithy/property-provider": "^4.2.5",
"@smithy/types": "^4.9.0",
"@smithy/url-parser": "^4.2.5",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
@ -5442,16 +5717,13 @@
}
},
"node_modules/@smithy/fetch-http-handler": {
"version": "5.3.6",
"resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz",
"integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==",
"dev": true,
"version": "5.6.13",
"resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.6.13.tgz",
"integrity": "sha512-4fW86pEUOMbrD5nkbyl/tTvPHHWJFbuB2odl6ps9lWfHoXf9HWh3Q/Smh59qH1g7+c/BSZghX6bbUk4gsiMs8A==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/protocol-http": "^5.3.5",
"@smithy/querystring-builder": "^4.2.5",
"@smithy/types": "^4.9.0",
"@smithy/util-base64": "^4.3.0",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
@ -5603,16 +5875,13 @@
}
},
"node_modules/@smithy/node-http-handler": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz",
"integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==",
"dev": true,
"version": "4.9.13",
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.9.13.tgz",
"integrity": "sha512-Nmd/Nl35zfYrd+a6OO2cDJb3GPh9bgTjIUhcM+JFfjpp8/osCgboDV5nCT1I01Pv6R13eSKDKLSoVa5ZB6Zsfw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/abort-controller": "^4.2.5",
"@smithy/protocol-http": "^5.3.5",
"@smithy/querystring-builder": "^4.2.5",
"@smithy/types": "^4.9.0",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
@ -5647,21 +5916,6 @@
"node": ">=18.0.0"
}
},
"node_modules/@smithy/querystring-builder": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz",
"integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^4.9.0",
"@smithy/util-uri-escape": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/querystring-parser": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz",
@ -5704,19 +5958,13 @@
}
},
"node_modules/@smithy/signature-v4": {
"version": "5.3.5",
"resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz",
"integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==",
"dev": true,
"version": "5.6.12",
"resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.6.12.tgz",
"integrity": "sha512-I6KLtq3H0qqSuV9vLglfi8puHqzygzWHOnI4z/Rdoo+q50vvo18vBRdPAvvEtcaKROz7Zn6qnPa14kRfPH6PcQ==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^4.2.0",
"@smithy/protocol-http": "^5.3.5",
"@smithy/types": "^4.9.0",
"@smithy/util-hex-encoding": "^4.2.0",
"@smithy/util-middleware": "^4.2.5",
"@smithy/util-uri-escape": "^4.2.0",
"@smithy/util-utf8": "^4.2.0",
"@smithy/core": "^3.31.1",
"@smithy/types": "^4.16.1",
"tslib": "^2.6.2"
},
"engines": {
@ -5743,10 +5991,9 @@
}
},
"node_modules/@smithy/types": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz",
"integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==",
"dev": true,
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.16.1.tgz",
"integrity": "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@ -5950,19 +6197,6 @@
"node": ">=18.0.0"
}
},
"node_modules/@smithy/util-uri-escape": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz",
"integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/util-utf8": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz",
@ -8016,7 +8250,6 @@
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.1.tgz",
"integrity": "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==",
"dev": true,
"license": "MIT"
},
"node_modules/brace-expansion": {

View file

@ -12,6 +12,7 @@
},
"dependencies": {
"@anthropic-ai/sdk": "^0.91.1",
"@aws-sdk/client-route-53": "^3.1104.0",
"@better-auth/cli": "^1.4.10",
"@hookform/resolvers": "^5.2.2",
"@radix-ui/react-accordion": "^1.2.12",