Skip to main content

Session Report — AP-T11-024 Channel-Manager Hardening Arc

Date: 2026-05-01 (full day, multiple sub-sessions) Mode: Autonomous from "resume" + per-bundle directives Specs:

Plans:


Outcome at a glance​

BundleScopeStatusRepos touched
AP-T11-023Canonical OtaBookingCancelledEvent + modification consumer UPDATE flowDONEapi-contracts, messaging, channel-service, reservation-service
AP-T11-024 Item 5Remove DEBUG_RAW_RESAVENUE_PAYLOAD flagDONEchannel-service
AP-T11-024 Item 4Audit RS256 enforcement on WS gateways (already shipped under AP-CC-3)DONE — doc rewrite onlyhmp-docs
AP-T11-024 Item 6New inbound-channel-event-flow.md operator referenceDONEhmp-docs
AP-T11-024 Phase 2.5Backend role split — POST /intermediary/connections SUPER_ADMIN only + endpoint added to strip listDONEchannel-service
AP-T11-024 Phase 3.1Prisma migration — IntermediaryProviderConfig + TenantProviderEnrolment tables + nullable providerId FKDONEchannel-service
AP-T11-024 Phase 3.2IntermediaryResolverService (default-OFF, 5-min cache)DONEchannel-service
AP-T11-024 Phase 3.3Seed 4 default provider rows (RESAVENUE/STAAH/EZEE/CHANNELRUSH)DONEinfrastructure (seed-master.sh)
AP-T11-024 Phase 3.4Backfill script migrate-provider-config.ts (idempotent + dry-run)DONEchannel-service
AP-T11-024 Phase 3.55 SUPER_ADMIN endpoints under /providers/* (list, get, allowlist PUT, secret rotate, PATCH)DONEchannel-service, api-gateway
AP-T11-024 Phase 3.6Receiver-side cutover wiring (resolver call, default-OFF flag)DONEchannel-service
AP-T11-024 Phase 4EIP allowlist enforcement mode (ENFORCE/SHADOW/OFF) on receiverDONEchannel-service
AP-T11-024 Phase 4BIntermediaryAuditAnomalyDetectorService — 5 anomaly conditionsDONEchannel-service
AP-T11-024 Phase 4CIntermediaryConfigNotifierService — Slack audit + anomaly webhooksDONEchannel-service
AP-T11-024 Phase 4DPinningHttpsAgentFactory + cert-pinning schema (default OFF)DONE — adapter wiring deferredchannel-service
AP-T11-024 Phase 4D PATCHcertPinningMode + certThumbprintsSha256 on PATCH /providers/:codeDONEchannel-service
AP-T11-024 Phase 4A backend4-eyes approval workflow — state machine + 7 SUPER_ADMIN endpointsDONEchannel-service, api-gateway
AP-T11-024 Phase 2 (C bundle)7 admin portal pages + dashboard slim-downDONE — browser smoke pendingadmin-portal, web-dashboard
AP-T11-024 admin endpointsGET /api/intermediary/admin/connections (cross-tenant) + GET /changes (cross-provider)DONEchannel-service
AP-T11-024 cert UI editorCert-pinning editor card in Overview tabDONEadmin-portal
AP-T11-024 component tests5 wizard + 5 queue Vitest specs (no Playwright in admin-portal)DONEadmin-portal

Aggregate: 21 distinct shipping items across 4 phases, 13 audit branches all merged + pushed to origin/master across 5 repos (channel-service, api-gateway, admin-portal, web-dashboard, hmp-docs) + the supporting infrastructure repo seed.

Final repo HEADs​

Repomaster HEADLatest commit
hmp-channel-service450b24dPhase 4D PATCH support
hmp-api-gatewaydd4cf98gateway /changes route
hmp-admin-portal8e21f99admin portal follow-ups (wired endpoints + cert UI + tests)
hmp-web-dashboard07dc452Phase 2.6 dashboard slim-down
hmp-docs0107bcePhase 4 spec + plan
hmp-infrastructure6bfb645intermediary providers seed

Key product / security decisions captured​

IDQuestionDecision
Three-tier modelTier-1 / Tier-2 / Tier-3 split for channel configAdopted — Tier-1 (provider catalog, allowlist, secret) lives on IntermediaryProviderConfig and is SUPER_ADMIN-only via admin portal; Tier-2 (chain enrolment) on TenantProviderEnrolment; Tier-3 (per-property toggles, mappings) stays on IntermediaryConnection editable by MANAGER+
Receiver cutover gateWhen does receiver read from provider row?INTERMEDIARY_PROVIDER_TABLE_ENABLED=true AND backfill ran AND 1-week QA soak — three-of-three required
Shadow mode defaultShould non-ENFORCE be a per-provider or per-connection setting?Both — per-connection override wins over provider-level default; chain admins can pilot SHADOW on one tenant while everyone else stays ENFORCE
Cert pinning rolloutOFF→WARN→STRICT progression?Yes — operator captures live cert thumbprint, sets WARN, soaks 7 days, flips STRICT. Dual-pin during partner cert rotation (multiple thumbprints in array).
4-eyes approvalMandatory on every Tier-1 write?Yes when INTERMEDIARY_FOUR_EYES_ENABLED=true. Two-actor enforcement at service layer (proposer_cannot_approve). Emergency override path with rate limit (2 per actor per 24h) for production hotfixes.
Browser verification gateCode complete vs production-readyCode complete ≠ production-ready until browser smoke-test pass. Per CLAUDE.md "if you can't test the UI, say so explicitly" — admin portal C bundle is in this state today.

What's still open after today​

Browser verification​

  • Local smoke-test pass on the new admin portal pages with seeded data (~1hr next session)

Calendar-bound (NOT code work)​

  • A1 — ResAvenue cert sign-off (external; awaiting Manish's reply on cert email v2 sent 2026-04-30 evening)
  • D.7 — 1-week QA soak after INTERMEDIARY_PROVIDER_TABLE_ENABLED=true
  • D.8 — Strip migration removing whitelistedIps/webhookSecret/endpoint from IntermediaryConnection.credentials JSON (after D.7)
  • E.4D adapter wiring — when ResAvenue's live endpoint switches to HTTPS (today: HTTP 203.109.97.241:8080)

Operational follow-ups (cross-cutting infra, ~1-2 days each)​

  • PagerDuty bridge from the pagerduty_alerts table to PagerDuty Events API
  • Slack webhook URLs in staging/prod Helm values (SLACK_CHANNEL_AUDIT_WEBHOOK + SLACK_CHANNEL_ANOMALY_WEBHOOK)
  • BullMQ retry consumer for APPROVED-but-not-APPLIED 4-eyes requests
  • Boot validator for accidental SHADOW-in-prod (Phase 4E.4b — single-line cron)

Nice-to-have​

  • Real-browser Playwright specs for admin portal (today: Vitest + RTL)
  • Cert-pinning rotation runbook in hmp-docs
  • "Withdrawn / Rejected / Applied" history view on the /admin/changes queue (today only PENDING is listed)

Production cutover playbook (when A1 lands)​

  1. Set CHANNEL_MODE=live + RESAVENUE_WEBHOOK_SECRET=<rotated> in prod env
  2. Use /admin/onboarding/connect-property-to-provider wizard to create the first live connection
  3. Run backfill: npx ts-node scripts/migrate-provider-config.ts --apply on QA → review dry-run output → --apply on prod
  4. Flip INTERMEDIARY_PROVIDER_TABLE_ENABLED=true in prod
  5. Watch QA + prod for 7 days (D.7)
  6. Ship strip migration (D.8); ramp cert-pinning OFF→WARN→STRICT in parallel; flip 4-eyes on (INTERMEDIARY_FOUR_EYES_ENABLED=true)

Tests added​

SuiteRepoCount
intermediary-role-gate.spec.ts (Phase 2.5)channel-service10
intermediary-resolver.service.spec.ts (Phase 3.2 + 4E)channel-service12
providers.service.spec.ts (Phase 3.5 + 4D PATCH)channel-service16
intermediary-admin.service.spec.ts (admin endpoint)channel-service5
change-request.service.spec.ts (Phase 4A + listAllChanges)channel-service18
intermediary-audit-anomaly-detector.spec.ts (Phase 4B)channel-service12
intermediary-config-notifier.spec.ts (Phase 4C)channel-service10
pinning-https-agent.factory.spec.ts (Phase 4D)channel-service15
resavenue-webhook-booking.spec.ts (Phase 4E receiver branches)channel-service+4
Wizard component testadmin-portal5
Queue page component testadmin-portal5
Total new112 specs

Migration files added​

MigrationRepoPurpose
20260601_intermediary_providerchannel-servicePhase 3.1 — IntermediaryProviderConfig + TenantProviderEnrolment tables
20260602_intermediary_phase4channel-servicePhase 4E — IntermediaryEnforcementMode enum + 2 columns
20260603_intermediary_cert_pinningchannel-servicePhase 4D — cert pinning fields
20260604_intermediary_four_eyeschannel-servicePhase 4A — IntermediaryConfigChangeRequest table + 2 enums

All idempotent; all default-OFF in behavior.