diff --git a/README.md b/README.md index bc7c70d..40b5849 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,24 @@ Slack DM ▼ API Gateway (bot.seahaven.com) │ - ▼ -slack-webhook Lambda ← verifies Slack signature, returns 200 immediately - │ (async invoke) - ▼ -slack-processor Lambda ← calls Bedrock Agent, logs to DynamoDB, posts reply + ├── POST /slack/events + │ ▼ + │ slack-webhook Lambda ← verifies Slack signature, returns 200 immediately + │ │ (async invoke) + │ ▼ + │ slack-processor Lambda ← calls Bedrock Agent, logs to DynamoDB, posts reply + │ │ + │ ▼ + │ Bedrock Agent (Claude Sonnet 4.5) + │ ├── Knowledge Base (AOSS + S3) ← SA8000 docs, SOPs, employee handbook, Notion pages, POs, work orders, site list + │ ├── QBO_Lookup action group ← QuickBooks vendor search (VPC, static IP) + │ ├── Google_Maps_Lookup action group ← fallback vendor search + │ └── WO_PO_Lookup action group ← work order, purchase order, and site lookups (DynamoDB direct) │ - ▼ -Bedrock Agent (Claude Sonnet 4.5) - ├── Knowledge Base (AOSS + S3) ← SA8000 docs, SOPs, employee handbook, Notion pages, POs, work orders, site list - ├── QBO_Lookup action group ← QuickBooks vendor search - ├── Google_Maps_Lookup action group ← fallback vendor search - └── WO_PO_Lookup action group ← work order, purchase order, and site lookups (DynamoDB direct) + └── GET /qbo/* + ▼ + qbo-oauth Lambda (VPC, static IP) ← OAuth 2.0 connect/callback/disconnect/launch + Outbound IP: 52.202.83.13 (NAT Gateway in seahaven-vpc) EventBridge (daily 02:00 UTC) │ @@ -48,7 +54,10 @@ EventBridge (daily 02:00 UTC) | PO Data Source | DynamoDB `purchase-orders` (via po-ingest) | | Work Order Data Source | DynamoDB `WorkOrders` + `WorkOrderComments` (via workorder-ingest) | | Site Assignments | DynamoDB `SiteAssignments` (seeded from CSV via `scripts/seed-sites.ts`) | +| VPC | `seahaven-vpc` (`vpc-0d3d4b67bd0cf8a68`) — QBO Lambdas only | +| Static Outbound IP | `52.202.83.13` (NAT Gateway for Intuit IP allowlist) | | Webhook URL | `https://bot.seahaven.com/slack/events` | +| QBO OAuth URLs | `/qbo/connect`, `/qbo/callback`, `/qbo/disconnect`, `/qbo/launch` | ## Prerequisites @@ -64,7 +73,7 @@ These secrets must exist before deploying. The Slack, QBO, and Maps secrets must | Secret Name | Created | Structure | |---|---|---| | `seahaven/slack/credentials` | Manual (pre-deploy) | `{ "botToken": "xoxb-...", "signingSecret": "..." }` | -| `seahaven/qbo/oauth` | Manual (pre-deploy) | `{ "clientId": "", "clientSecret": "", "refreshToken": "", "realmId": "" }` | +| `seahaven/qbo/oauth` | Manual (pre-deploy) | `{ "clientId": "", "clientSecret": "", "refreshToken": "", "realmId": "" }` — refreshToken and realmId are auto-populated via `/qbo/connect` OAuth flow | | `seahaven/google/maps-api-key` | Manual (pre-deploy) | `{ "apiKey": "" }` | | `seahaven/notion/api-key` | Auto (CDK) | `{ "apiKey": "secret_..." }` | @@ -145,7 +154,7 @@ lib/ constructs/ knowledge-base.ts Bedrock KB + AOSS + S3 (via @cdklabs L2 construct) bedrock-agent.ts Bedrock Agent + QBO/Maps/WO-PO-Site action groups - slack-handler.ts API Gateway + webhook/processor Lambdas + slack-handler.ts API Gateway + webhook/processor Lambdas + QBO OAuth Lambda conversation-log.ts DynamoDB table notion-sync.ts EventBridge daily cron + notion-sync Lambda + Secrets Manager po-sync.ts EventBridge daily cron + po-sync Lambda @@ -153,6 +162,7 @@ lib/ lambda/ slack-webhook/ Verifies Slack signature, fires processor async slack-processor/ Calls agent, writes DynamoDB, posts Slack reply + qbo-oauth/ OAuth 2.0 connect/callback/disconnect/launch for QuickBooks qbo-lookup/ Bedrock action group — QuickBooks vendor search maps-lookup/ Bedrock action group — Google Maps Places search wo-po-lookup/ Bedrock action group — WO, PO, and site code lookups (DynamoDB direct) @@ -166,7 +176,7 @@ scripts/ ## Known Maintenance Items -- **QBO refresh token** expires after 100 days of inactivity. Rotate via the [Intuit OAuth Playground](https://developer.intuit.com/app/developer/playground) and update the `seahaven/qbo/oauth` secret. +- **QBO OAuth** — the refresh token auto-rotates on every API call (persisted back to Secrets Manager). If the token ever expires (100 days of inactivity), reconnect via `https://bot.seahaven.com/qbo/connect`. To disconnect, visit `/qbo/disconnect`. - **Notion sync** runs daily at 02:00 UTC automatically. To trigger an immediate sync, invoke `seahaven-notion-sync` manually via the Lambda console or CLI. - **PO sync** runs daily at 02:00 UTC. Scans the `purchase-orders` DynamoDB table (from [po-ingest](https://github.com/Sea-Haven-Industries/po-ingest)) and exports each PO as markdown to the KB. Manual trigger: invoke `seahaven-po-sync`. - **Work order sync** runs daily at 02:00 UTC. Scans `WorkOrders` and `WorkOrderComments` DynamoDB tables (from [workorder-ingest](https://github.com/Sea-Haven-Industries/workorder-ingest)) and exports each work order + comment history as markdown to the KB. Manual trigger: invoke `seahaven-workorder-sync`.