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:
2026-05-01-platform-vs-property-channel-config-separation-design.md(Phase 1-3)2026-05-01-channel-config-hardening-design.md(Phase 4)2026-05-01-ota-booking-canonical-event-contract-design.md(AP-T11-023)
Plans:
2026-05-01-channel-config-separation-phased-execution.md2026-05-01-channel-config-hardening-phased-execution.md2026-05-01-channel-config-c-d-e-execution.md
Outcome at a glance
| Bundle | Scope | Status | Repos touched |
|---|---|---|---|
| AP-T11-023 | Canonical OtaBookingCancelledEvent + modification consumer UPDATE flow | DONE | api-contracts, messaging, channel-service, reservation-service |
| AP-T11-024 Item 5 | Remove DEBUG_RAW_RESAVENUE_PAYLOAD flag | DONE | channel-service |
| AP-T11-024 Item 4 | Audit RS256 enforcement on WS gateways (already shipped under AP-CC-3) | DONE — doc rewrite only | hmp-docs |
| AP-T11-024 Item 6 | New inbound-channel-event-flow.md operator reference | DONE | hmp-docs |
| AP-T11-024 Phase 2.5 | Backend role split — POST /intermediary/connections SUPER_ADMIN only + endpoint added to strip list | DONE | channel-service |
| AP-T11-024 Phase 3.1 | Prisma migration — IntermediaryProviderConfig + TenantProviderEnrolment tables + nullable providerId FK | DONE | channel-service |
| AP-T11-024 Phase 3.2 | IntermediaryResolverService (default-OFF, 5-min cache) | DONE | channel-service |
| AP-T11-024 Phase 3.3 | Seed 4 default provider rows (RESAVENUE/STAAH/EZEE/CHANNELRUSH) | DONE | infrastructure (seed-master.sh) |
| AP-T11-024 Phase 3.4 | Backfill script migrate-provider-config.ts (idempotent + dry-run) | DONE | channel-service |
| AP-T11-024 Phase 3.5 | 5 SUPER_ADMIN endpoints under /providers/* (list, get, allowlist PUT, secret rotate, PATCH) | DONE | channel-service, api-gateway |
| AP-T11-024 Phase 3.6 | Receiver-side cutover wiring (resolver call, default-OFF flag) | DONE | channel-service |
| AP-T11-024 Phase 4E | IP allowlist enforcement mode (ENFORCE/SHADOW/OFF) on receiver | DONE | channel-service |
| AP-T11-024 Phase 4B | IntermediaryAuditAnomalyDetectorService — 5 anomaly conditions | DONE | channel-service |
| AP-T11-024 Phase 4C | IntermediaryConfigNotifierService — Slack audit + anomaly webhooks | DONE | channel-service |
| AP-T11-024 Phase 4D | PinningHttpsAgentFactory + cert-pinning schema (default OFF) | DONE — adapter wiring deferred | channel-service |
| AP-T11-024 Phase 4D PATCH | certPinningMode + certThumbprintsSha256 on PATCH /providers/:code | DONE | channel-service |
| AP-T11-024 Phase 4A backend | 4-eyes approval workflow — state machine + 7 SUPER_ADMIN endpoints | DONE | channel-service, api-gateway |
| AP-T11-024 Phase 2 (C bundle) | 7 admin portal pages + dashboard slim-down | DONE — browser smoke pending | admin-portal, web-dashboard |
| AP-T11-024 admin endpoints | GET /api/intermediary/admin/connections (cross-tenant) + GET /changes (cross-provider) | DONE | channel-service |
| AP-T11-024 cert UI editor | Cert-pinning editor card in Overview tab | DONE | admin-portal |
| AP-T11-024 component tests | 5 wizard + 5 queue Vitest specs (no Playwright in admin-portal) | DONE | admin-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
| Repo | master HEAD | Latest commit |
|---|---|---|
hmp-channel-service | 450b24d | Phase 4D PATCH support |
hmp-api-gateway | dd4cf98 | gateway /changes route |
hmp-admin-portal | 8e21f99 | admin portal follow-ups (wired endpoints + cert UI + tests) |
hmp-web-dashboard | 07dc452 | Phase 2.6 dashboard slim-down |
hmp-docs | 0107bce | Phase 4 spec + plan |
hmp-infrastructure | 6bfb645 | intermediary providers seed |
Key product / security decisions captured
| ID | Question | Decision |
|---|---|---|
| Three-tier model | Tier-1 / Tier-2 / Tier-3 split for channel config | Adopted — 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 gate | When 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 default | Should 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 rollout | OFF→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 approval | Mandatory 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 gate | Code complete vs production-ready | Code 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/endpointfromIntermediaryConnection.credentialsJSON (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_alertstable 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/changesqueue (today only PENDING is listed)
Production cutover playbook (when A1 lands)
- Set
CHANNEL_MODE=live+RESAVENUE_WEBHOOK_SECRET=<rotated>in prod env - Use
/admin/onboarding/connect-property-to-providerwizard to create the first live connection - Run backfill:
npx ts-node scripts/migrate-provider-config.ts --applyon QA → review dry-run output →--applyon prod - Flip
INTERMEDIARY_PROVIDER_TABLE_ENABLED=truein prod - Watch QA + prod for 7 days (D.7)
- Ship strip migration (D.8); ramp cert-pinning OFF→WARN→STRICT in parallel; flip 4-eyes on (
INTERMEDIARY_FOUR_EYES_ENABLED=true)
Tests added
| Suite | Repo | Count |
|---|---|---|
intermediary-role-gate.spec.ts (Phase 2.5) | channel-service | 10 |
intermediary-resolver.service.spec.ts (Phase 3.2 + 4E) | channel-service | 12 |
providers.service.spec.ts (Phase 3.5 + 4D PATCH) | channel-service | 16 |
intermediary-admin.service.spec.ts (admin endpoint) | channel-service | 5 |
change-request.service.spec.ts (Phase 4A + listAllChanges) | channel-service | 18 |
intermediary-audit-anomaly-detector.spec.ts (Phase 4B) | channel-service | 12 |
intermediary-config-notifier.spec.ts (Phase 4C) | channel-service | 10 |
pinning-https-agent.factory.spec.ts (Phase 4D) | channel-service | 15 |
resavenue-webhook-booking.spec.ts (Phase 4E receiver branches) | channel-service | +4 |
| Wizard component test | admin-portal | 5 |
| Queue page component test | admin-portal | 5 |
| Total new | 112 specs |
Migration files added
| Migration | Repo | Purpose |
|---|---|---|
20260601_intermediary_provider | channel-service | Phase 3.1 — IntermediaryProviderConfig + TenantProviderEnrolment tables |
20260602_intermediary_phase4 | channel-service | Phase 4E — IntermediaryEnforcementMode enum + 2 columns |
20260603_intermediary_cert_pinning | channel-service | Phase 4D — cert pinning fields |
20260604_intermediary_four_eyes | channel-service | Phase 4A — IntermediaryConfigChangeRequest table + 2 enums |
All idempotent; all default-OFF in behavior.