Commit graph

25 commits

Author SHA1 Message Date
4b5991bd14
Remove state-listing path from wo-po-lookup site lookups
The verified-sites table's by-state GSI was deleted by its owning
stack (procurement-ingest, audit M-20, 2026-06-03, "0 reads in 30d"),
so the state-listing branch of lookup_site has failed at runtime ever
since. Per the owner's decision, remove the path end-to-end instead
of restoring the GSI: drop the by-state Query from the Lambda, remove
the state parameter from the WO_PO_Lookup lookup_site function schema
(site_code is now required), strip state listings from the agent
instruction, and update the README data-contract table. siteCode
point lookups are unaffected. A stale state parameter from an older
prepared agent version now returns a clear "no longer supported"
message.

Refs: INFRA-180
2026-07-15 18:49:05 -04:00
Adam Moussa
46f568f6ea
feat(slack-bot): codify kms:Decrypt grants for CMK'd DynamoDB readers (INFRA-95 / M-3) (#51)
wo-po-lookup, po-sync, and workorder-sync read WorkOrders,
WorkOrderComments, purchase-orders and PaymentsDashboard, which are now
SSE-encrypted with alias/seahaven-dynamodb. Tables are imported by name
so grantReadData adds no KMS perms; grant kms:Decrypt explicitly via the
CMK imported from SSM /seahaven/dynamodb/cmk-arn. Replaces the interim
CLI inline policy (Sid Infra95DynamoDbCmkDecrypt) with IaC.

INFRA-95
2026-06-09 12:33:06 -04:00
Adam Moussa
5175d39eb9
fix(kb): lock AOSS network policy to private with Bedrock source service (#49)
The @cdklabs/generative-ai-cdk-constructs VectorKnowledgeBase hardcodes
AllowFromPublic: true on the auto-created AOSS network policy and exposes
no prop to change it. Override the underlying CfnSecurityPolicy to set the
collection rule to AllowFromPublic: false with
SourceServices: ['bedrock.amazonaws.com'] — the latter is required to keep
Bedrock-managed retrieval working once public access is removed (a
SourceVPCEs-only policy returns 401 for Bedrock retrieve). Dashboard rule
kept public for console access; AWS services cannot reach Dashboards.

Same end state was applied live via update-security-policy and smoke-tested
(retrieve returns hits, top score ~0.40) so this deploy is a no-op convergence.

INFRA-92
2026-06-08 18:01:08 -04:00
Adam Moussa
de55c0eeca
feat(api): add access logging and throttling to webhook HTTP API (#46)
Adds an access log group (/aws/apigateway/seahaven-slack-webhook, 90-day
retention) with JSON access-log format and DefaultRouteSettings throttling
(rate 2 rps, burst 5) on the seahaven-slack-webhook HTTP API default stage,
applied via CfnStage property overrides. Matches the pattern landed on
seahaven-door-unlock-api.

Refs INFRA-29 (AWS audit M-18)
2026-06-05 17:47:44 -04:00
Adam Moussa
307a5ed661
fix: grant bedrock:GetGuardrail to agent execution role (#39)
The Bedrock Agents service fetches the guardrail config via GetGuardrail
before applying it. The role only had ApplyGuardrail, so every agent
invocation logged an AccessDenied and tripped the CIS 4.1
UnauthorizedAPICalls alarm.

Scoped to the same guardrail ARNs already granted for ApplyGuardrail.
Cross-reviewed (IAM change): APPROVE, no findings.
2026-06-04 16:50:19 -04:00
Adam Moussa
a3457be911
Add guardrail to seahaven-alex agent (#38)
Audit finding M-19: the employee-facing assistant had no guardrail
despite access to QBO, payments, WO/PO, and HR/SA8000 data.

Adds prompt-attack (HIGH input), content filters, and masking of
credential/financial identifiers (SSN, cards, bank numbers, keys).
Names/emails/phones deliberately unmasked - vendor contact lookup is
the bot's core function. MISCONDUCT output at MEDIUM so SA8000
misconduct-reporting questions are not suppressed.

Cross-reviewed (1 BLOCK fixed: ApplyGuardrail now covers version-
suffixed ARNs; explicit guardrail->version->agent dependencies added).
Alias description bump forces a new agent version (v10) so the live
alias snapshots the guardrail config.
2026-06-03 15:16:06 -04:00
Adam Moussa
50da33712b
Set explicit arm64 platform on Docker image build (#30)
fromAsset() builds for the host architecture by default. On x86_64
GitHub Actions runners, this produces an x86 image even with QEMU
installed — the Fargate ARM64 task then fails with exec format error.
2026-05-08 17:58:28 -04:00
Adam Moussa
006dbf7c6b feat: Alex rollout — persona, Socket Mode, payments, channels, App Home, unanswered questions
- Rename bot to Alex with friendly/professional persona (Bedrock Agent instruction rewrite)
- Replace HTTP webhook Lambda with ECS Fargate Socket Mode service (persistent WebSocket)
- Add payment/invoice lookup via PaymentsDashboard table (vendor, invoice, check search)
- Switch from manual SiteAssignments to auto-populated verified-sites table
- Add channel support via app_mention events (threaded replies)
- Add App Home tab with Block Kit capabilities view
- Add unanswered questions logging to seahaven-unanswered-questions DynamoDB table
- Fix pre-existing compliance: add arm64 + 60-day log retention to all Lambdas
- Remove webhook Lambda and seed-sites script (both obsolete)
2026-04-30 16:38:54 -04:00
Adam Moussa
d1b91ae661 Read OAuth client credentials from Secrets Manager at runtime
Removes CloudFormation dynamic references for clientId/clientSecret
env vars. Credentials are now fetched from Secrets Manager at runtime
so secret updates don't require a redeploy.
2026-04-13 20:22:21 -04:00
Adam Moussa
066ff59d22 Place QBO Lambdas in VPC for static outbound IP
Puts qbo-lookup and qbo-oauth Lambdas in seahaven-vpc private subnets
so all outbound traffic routes through NAT Gateway (52.202.83.13).
Required for Intuit app listing IP allowlist.
2026-04-13 19:51:00 -04:00
Adam Moussa
acfe8185a9 Add QBO OAuth endpoints for QuickBooks app listing
Adds /qbo/connect, /qbo/callback, /qbo/disconnect, and /qbo/launch
routes to bot.seahaven.com for Intuit app store compliance. Also
updates qbo-lookup to persist rotated refresh tokens automatically.
2026-04-13 19:31:13 -04:00
Adam Moussa
fb026dfd72 Add Amazon site assignments lookup via DynamoDB
- Create SiteAssignments DynamoDB table with state GSI for site code and
  state-based queries
- Add lookup_site function to wo-po-lookup action group lambda
- Add seed script (scripts/seed-sites.ts) to load site CSV into DynamoDB
- Upload site list markdown to KB S3 bucket for semantic search
- Update agent instruction to include site lookup capability
- Update README with site assignment docs and maintenance notes
2026-04-13 19:11:39 -04:00
Adam Moussa
8cb762d055 Fix agent identity: clarify that we ARE Sea Haven, not an external vendor
The bot was suggesting Sea Haven as a vendor to contact because it didn't
understand it belongs to Sea Haven. Updated system prompt to make clear
that Sea Haven is our company and "local vendor" means a subcontractor.
2026-04-13 18:50:35 -04:00
Adam Moussa
8b6e65bd20 Improve Slack formatting for WO/PO lookups
- Add markdown-to-Slack mrkdwn conversion in processor (** → *, ## → bold)
- Restructure lambda output with cleaner sections and date formatting
- Update agent instruction to present data concisely
2026-04-13 18:34:47 -04:00
Adam Moussa
24ebe8bdcc Add WO/PO direct lookup action group for reliable ID-based queries
Vector search couldn't match exact work order/PO numbers, so queries
always came back empty. This adds a dedicated lambda that queries
DynamoDB directly by ID, wired as a Bedrock Agent action group.
2026-04-13 17:59:47 -04:00
Adam Moussa
5943b775eb Update agent alias description to force version bump on deploy 2026-04-13 17:15:11 -04:00
Adam Moussa
510834533b Add work order and purchase order lookups to Bedrock agent instructions
The agent's system prompt and KB description didn't mention WO/PO data,
so it refused queries even though the data was already in the knowledge base.
2026-04-13 17:05:26 -04:00
Adam Moussa
40216430c6 Merge master after PO sync PR merge 2026-04-13 15:38:13 -04:00
Adam Moussa
adbe19aa16 fix: concurrent uploads, overwrite-in-place, 15min timeout
- Bump Lambda timeout from 5min to 15min (9k+ POs need more time)
- Upload S3 files 25x concurrently instead of sequentially
- Replace clear-then-write with overwrite-in-place + delete stale
  to avoid S3 404s during concurrent KB ingestion jobs
2026-04-13 15:36:07 -04:00
Adam Moussa
7240147736 feat: daily work orders DynamoDB → Bedrock KB sync
Add a new Lambda and CDK construct that scans the WorkOrders and
WorkOrderComments DynamoDB tables (owned by workorder-ingest),
converts each work order + comment history to markdown, uploads
to S3 under the work-orders/ prefix, and triggers a Bedrock
Knowledge Base ingestion job. Runs daily at 02:00 UTC via
EventBridge alongside the existing Notion sync.
2026-04-13 14:35:47 -04:00
Adam Moussa
615970eba2 feat: daily purchase-orders DynamoDB → Bedrock KB sync
Add a new Lambda and CDK construct that scans the purchase-orders
DynamoDB table (owned by po-ingest), converts each PO to markdown,
uploads to S3 under the purchase-orders/ prefix, and triggers a
Bedrock Knowledge Base ingestion job. Runs daily at 02:00 UTC via
EventBridge alongside the existing Notion sync.
2026-04-13 14:33:53 -04:00
8b18279023 feat: daily Notion → Bedrock KB sync
Adds a scheduled Lambda that pulls all pages from the Office Operations
Notion teamspace, converts them to markdown, uploads to the KB S3 bucket
under a notion/ prefix, and triggers a Bedrock ingestion job. Runs daily
at 02:00 UTC via EventBridge. Notion API key stored in Secrets Manager at
seahaven/notion/api-key (placeholder — fill in post-deploy).
2026-04-12 22:21:39 -04:00
Adam Moussa
505b624242 Add thinking placeholder and improve location parameter handling
- Post '_Sea Haven Assistant is thinking..._' immediately on receipt,
  then update the message with the real response (chat.update)
- Broaden Maps location parameter description so agent passes facility
  names like 'Amazon BFI9' directly to Google Maps rather than asking
  the user to provide a street address
2026-04-12 00:01:33 -04:00
Adam Moussa
635e712966 Switch to Claude Sonnet 4.5 cross-region inference profile
- Update foundation model to us.anthropic.claude-sonnet-4-5-20250929-v1:0
  (cross-region inference profile required for Claude 4.x on Bedrock Agents)
- Broaden agent role IAM policy to cover wildcard-region foundation model ARN
  and inference profile ARN
- Force alias version bump via description change so CloudFormation creates
  agent version 2 with the updated model
- Remove invalid includedType: 'contractor' from Google Maps Places API request
  (caused 400 Bad Request — not a valid place type for searchText endpoint)
2026-04-11 23:52:44 -04:00
Adam Moussa
f7e63e50c9 Initial scaffold: Bedrock-backed Slack DM bot
- CDK stack for Sea Haven Industries internal Slack assistant
- Bedrock Agent (Claude 3.5 Sonnet) with QBO + Google Maps action groups
- VectorKnowledgeBase via @cdklabs/generative-ai-cdk-constructs (AOSS + S3)
- Slack webhook/processor Lambdas with DM-only filtering
- API Gateway HTTP API on bot.seahaven.com
- DynamoDB conversation log with 90-day TTL
- Secrets Manager references for Slack, QBO OAuth, and Google Maps
2026-04-11 23:15:15 -04:00