Mobile responsiveness: several flex rows had a `truncate` child without
`min-w-0`, so a long value (member/door name, channel name, published form
URL) would not shrink and pushed the row past the viewport on a phone. Added
`min-w-0` (with `flex-1`/`shrink-0` where needed) on the dashboard presence +
door-self-entry rows, the comms channel list, and the form-builder URL.
Door inbound poll: `/api/cron/door-ingest` now polls connections with
Promise.allSettled instead of a sequential loop, so one tick is bounded to the
slowest single poll rather than the sum of all per-call timeouts; each
connection stays isolated and the run is idempotent.
Docs: refreshed ARCHITECTURE (door epic marked complete P1-P5), the README
access-control feature bullet + project-status pointer, a historical banner on
the older AUDIT.md, a door-epic CHANGELOG entry, and the rolling HANDOFF audit
log (passes 65-68). No migration; no behavior change for existing users.
Phase 4 (migration 053): pull entry/denied events into door_access_log and
match each card to a member, via two transports sharing one ingest core.
Poll: a CRON_SECRET-guarded /api/cron/door-ingest reads each opted-in
native-HeatSync connection's ?z log through the existing hardened executor
and parses it (firmware-characterized, best-effort ring buffer). Webhook:
/api/door/inbound/[connection] accepts pushed event JSON authenticated by a
per-connection bearer secret from the vault. Both dedupe on
(connection_id, dedupe_key) so re-polls and retries are no-ops. Adds an
inbound config panel to /door/manage.
Phase 5 (migration 054): admins define api_buttons that fire a configured
HTTP call (full verbs + headers + body) when an authorized member presses
them, through the same hardened egress (now shared between callDoor and the
new callApi). Each button carries a required_permission (default the new
apicall.invoke code); members see only buttons they may press. Builder at
/door/buttons with a door-template preset; members press from /doors. Every
press is recorded in api_call_log with secrets redacted.
Both subsystems are inert until an admin enables inbound on a connection or
creates a button. 624 unit + 50 integration tests; migrations applied
top-to-bottom in schema.sql; types and docs updated.