Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions .azure/deployment-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
**Direction: subscription-free attendee lab; existing-resource presenter capstone.**
No new Azure deployment is required for the selected workshop. The organizer has
an existing Azure DocumentDB instance available for a presenter-only demonstration.
Availability is not a claim that the application round trip has been rehearsed.
A previous local Mac mini → managed Azure round trip passed; this does not
prove the delivery revision on the conference laptop/network.

## Mandatory attendee path

Expand Down Expand Up @@ -62,14 +63,22 @@ Automated gates in this revision:
- Complete-reference recovery and expected 216-entry catalog.
- No cloud endpoint used by attendee startup or database integration tests.

Still requiring environment-specific acceptance (not replaced by local/CI checks):
Executed on preceding main source (see [dated acceptance](../docs/acceptance.md)):

- [ ] Fresh revised attendee/organizer Codespaces builds and cold startup timing.
- [ ] Measured two-site resource needs on representative accounts/machines.
- [ ] Presenter actual laptop → approved managed Azure seed, copy-out, retry, copy-back.
- [ ] Approved real-network access and private credential delivery to the presenter.
- [ ] Verified backup recording and calendar-application import.
- [ ] Full 105-minute timed rehearsal, pairing fallback, export and safe stopping.
- [x] Fresh two-core attendee Codespace, 4m47s cold, actual Site A/B 34/34 plus integration.
- [x] Actual Google Calendar UI import, 3/3 events.
- [x] Local Mac mini → managed Azure round trip; temporary resource cleaned up.

Still requiring environment-specific acceptance (not replaced by those receipts):

- [x] Reconnect/onboarding revision: restarted attendee Codespace, 47/47 root tests,
2/2 live integration, same-app cold recovery and original-wait-process recovery;
interruption cleanup 2/2. See the dated acceptance record for exact source scope.
- [ ] New cold Codespace creation on this revision (the polish retest reused the existing one).
- [ ] Fresh Organizer profile and representative account/machine capacity checks.
- [ ] Presenter existing-resource rehearsal on the conference laptop/network.
- [ ] Verified backup recording; Apple Calendar UI and repeat-import handling.
- [ ] Full 105-minute human rehearsal, pairing fallback, export and safe stopping.

No unattended cleanup worker, cloud IAM grants, Kubernetes dependency, background
sync, Azure app hosting or new cloud resources are introduced by this plan.
14 changes: 14 additions & 0 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
cache: npm
- run: npm ci --ignore-scripts --no-audit --no-fund
- run: npm test
- run: npm run test:docs
- name: Start and seed only the two self-hosted sites
run: npm run workspace:start
- name: Exercise two independent database servers
Expand All @@ -31,3 +32,16 @@ jobs:
- name: Stop this ephemeral CI project only
if: always()
run: docker compose -f compose.yaml down --volumes

reconnect-regression:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: npm
- run: npm ci --ignore-scripts --no-audit --no-fund
- name: First-use failure, original wait process, concurrent recovery, healthy outage
run: npm run test:reconnect
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ usage; it is not a promise of free or offline hosting.

The app includes the [official ATO schedule](https://2026.allthingsopen.org/schedule)
snapshot captured October 12, 2026: **216 distinct scheduled entries, October 18–20**.
The earlier single-development-database app/API was rehearsed in Codespaces.
The revised two-site cold Codespaces startup, timed classroom delivery, calendar-app
import, and presenter Azure round trip still require their own acceptance rehearsal.
Automated local/CI checks are not proof of those environments.
On the preceding main source, a fresh **two-core attendee Codespace** reached both
sites in **4m47s**, actual Site A/B checks passed **34/34 plus integration**, Google
Calendar imported **3/3 events**, and a real **local Mac mini → managed Azure**
round trip passed (temporary cloud resource cleaned up). See the
[acceptance record](docs/acceptance.md) for scope. **This reconnect/onboarding
revision also passed a restarted-Codespace attendee run: 47/47 tests, actual
browser exercises, and cold first-connection recovery in the same app process.**
Timed human classroom delivery and conference-laptop networking are
not verified; automated checks are not substitutes.

The web schedule is primary; October 9 Monday/Tuesday PDFs were cross-checked,
not silently merged. See [source notes](docs/instructor.md#schedule-data) for
Expand All @@ -36,9 +41,13 @@ cross-listings, unresolved disagreements, and the excluded invalid break time.
private development credentials, starts both databases and the app, waits for
each database, and seeds the same catalog in both. It does not copy favorites.
3. When the terminal says **Site A and Site B are ready and both catalogs are
seeded**, open port **3000** in the **Ports** tab. Keep visibility **Private**.
4. Follow the [attendee guide](docs/lab.md). `TODO_LIST_SESSIONS` is intentional
until you finish the first exercise; it is not a database connection failure.
seeded**, select **Ports** beside Terminal in the editor's bottom panel. Find
row **3000** and use **Open in Browser** (globe). Keep visibility **Private**.
4. Follow the [attendee guide](docs/lab.md), also linked persistently in the planner.
The blue **Exercise 1** checkpoint is intentional, not a broken database.
5. Edit in Codespaces: **Explorer → exercises → starter → repository.js**, or
**Ctrl/Cmd+P**, then type `exercises/starter/repository.js`. A GitHub file link
is a read-only source view, not the editable file in your running Codespace.

Every workshop terminal command runs **inside Codespaces**, unless explicitly
following the optional [laptop-local appendix](docs/local.md).
Expand Down Expand Up @@ -163,7 +172,9 @@ The [captured source](data/schedule-source.json) and
[audit report](data/schedule-import-report.json) preserve provenance. A replacement
snapshot requires reviewed migration or fresh databases.

Calendar export is a snapshot, not a subscription. Published blocks may contain
Calendar export is a snapshot, not a subscription. Follow the
[Google Calendar / Apple Calendar import steps](docs/lab.md#9-take-your-selections-with-you).
Published blocks may contain
sequential keynotes/lightning talks; no per-talk timing is invented. Overlap
warnings need interpretation. Favorites neither reserve seats nor grant entry to
separately registered events.
Expand Down Expand Up @@ -205,6 +216,7 @@ With Node.js 24.13 or newer (already available inside Codespaces):
```sh
npm ci --ignore-scripts
npm test
npm run test:docs
```

With the two-site Compose stack running:
Expand All @@ -217,8 +229,11 @@ Integration checks use uniquely named temporary databases on **two different
local server services**, never the configured cloud endpoint. They remove only
their own temporary databases. Checks cover independent favorites, additive
round trips, timestamp/duplicate preservation, partial results, indexes,
migrations, and HTTP target switching. CI runs these checks on Linux; this is
not a live Azure or fresh Codespaces claim.
migrations with real before/after inspection, the optional read-only aggregation,
and HTTP target switching. For first-use failure/concurrent/wait-process recovery
on a **new isolated stack**, run `npm run test:reconnect` from the Docker host;
see [scope and cleanup](docs/acceptance.md#how-to-verify-the-revision). CI runs
these checks on Linux; this is not a fresh Codespaces or live Azure claim.

See the [lab](docs/lab.md), [instructor guide](docs/instructor.md),
[presenter runbook](docs/presenter.md), and [delivery plan](.azure/deployment-plan.md).
Expand Down
187 changes: 187 additions & 0 deletions docs/acceptance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# Acceptance record and remaining gates

## Executed evidence before the reconnect / attendee-polish revision

Recorded October 17, 2026 against the preceding main source
`e6eae569f0879ea59656c847db6c13a1dee0b7d1` (or tree-identical rehearsal source):

- **Fresh two-core attendee Codespace:** cold creation to both Site A/B catalogs
ready took **4 minutes 47 seconds** in that run. The actual Site A/B acceptance
checklist passed **34/34**, plus the live database integration test. This is
one measured environment, not a promised startup time for every account/network.
- **Attendee revisit:** the same Codespace was stopped/restarted and the two
starter exercises were completed again with new notebook database names.
Browsing, favorites, restart persistence, connection-only switching, selected
copying in both directions, safe repeat, migration and calendar download worked.
Editor focus required terminal assistance for the code replacements: not a
novice usability study or an entirely mouse-and-keyboard editing rehearsal.
- **Google Calendar web:** an actual downloaded calendar was imported through the
UI, **3/3 events**, with titles, timezones, UIDs, locations and Unicode checked.
No claim of Apple Calendar UI acceptance or universal repeat-import behavior.
- **Managed Azure data plane:** actual local **Mac mini workstation → managed
Azure DocumentDB** seed/switch/copy/retry/copy-back passed. The temporary cloud
resource used for that authorized test was cleaned up. This is real local-to-
managed evidence, not a conference-laptop/network rehearsal or an instruction
to provision attendee resources. Normal delivery still uses an approved
existing presenter resource and narrow access.

No account emails, private Codespace identifiers, subscription IDs, connection
strings or credentials are needed in this public record.

## Defect found during acceptance, and this revision's scope

The preceding source had a confirmed first-connection recovery defect with the
pinned MongoDB Node.js driver 7.1.0: if a cached client's first lazy connection
failed, later lazy commands could see a closed topology even after the database
was healthy. A previously connected client recovered from an ordinary outage.
The prior success record must **not** be read as proof of first-failure recovery;
restarting the app was then a workaround.

This revision explicitly awaits the driver's public `connect()` on every async
connection acquisition. The readiness CLI reacquires **inside** its retry loop.
It does not replay writes, change TLS policy, silently fall back to another site,
or replace credentials/volumes. Shutdown rejects new/racing acquisitions and
closes pools after pending connects settle.

New offline tests cover connection lifecycles, concurrent acquisition, bounded
wait retries, exercise guidance, bounded document inspection and the optional
query's snapshot-derived expected result. The live regression command below
checks first-use failure, the original waiting CLI process, concurrent clients,
a healthy-client outage control, unchanged favorite digests, and the **same app
PID** across recovery. A test added to source is not an executed live result.

## Executed reconnect / attendee-polish acceptance

Recorded October 17, 2026. The same attendee Codespace was restarted and rebuilt
from `8993fac38709a5d6cdece1f8170ffe9392111d14`, then fast-forwarded to
`a3f9c5aeb16f8350b3ece7ca74887987ddc94824` for the harness-only cleanup update.
That update changed no application/UI code; the final record update is docs-only.
Earlier notebooks, credentials, volumes and solved exercises were preserved with
private backups and separate fresh notebook database names.

- Final repository-root tests in Codespaces: **47/47 passed**, no skips;
**46 local documentation links** checked.
- Actual two-server database integration: **2/2 passed**, including the optional
official-catalog aggregation.
- Browser flow: blue Exercise 1, edit the first TODO, 216 entries, blue Exercise 2,
save overlapping favorites, persistence, initially empty Site B, two records
copied, repeat Already present, and a third favorite copied back. Complete-
reference switching preserved both solved files and notebook timestamps.
- **Main-app cold-connection regression:** Site B was stopped before that app
process ever acquired it. The browser switch failed with a genuine 503 and
stayed on Site A. After starting only Site B, the same browser retry succeeded
with the **same server PID, start time, container and request-token hash**.
No app restart or code edit was needed to recover.
- The isolated live harness independently proved recovery of the **original
waiting CLI process**, concurrent first acquisitions and a previously healthy
client. All scoped cleanup receipts passed.
- Interruption regressions: **2/2 passed** in Codespaces, including repeated
SIGINT/SIGTERM during cleanup and independent empty resource inventories.
- Actual document inspection showed the same session change from version 1 with
no attendanceMode to version 2/in-person. Migration changed **216 then 0**;
the favorite timestamp was unchanged. The optional solved database aggregation
returned **17 groups / 74 Monday entries**, matching the reference.
- Actual browser calendar download contained **three events**, validated against
the real state. This revision did not repeat the earlier Google Calendar import
or managed Azure test; calendar serialization and transfer semantics are unchanged.
- Resume to first SSH was about **39 seconds**; the explicit revised-code
build/start/seed took **27 seconds**, measured separately. Neither is a fresh
cold-creation measurement or a promised attendee timing.
- The exact Codespace was stopped and its **Shutdown** state verified; notebooks
and solved work remain retained. No new Azure resources were used in this retest.

Application actions and dialogs used a real browser; code edits used the
Codespaces CLI after locating the editable files. This is expert-assisted
acceptance, not a novice or timed classroom study. During premerge testing,
canonical main guide links still served the previous guide, so the trusted
branch guide was used; the docs and app are published together.

## How to verify the revision

Offline, from the repository root with Node 24.13+:

```sh
npm ci --ignore-scripts
npm test
npm run test:docs
```

On an already authorized attendee stack rebuilt from this source:

```sh
docker compose -f compose.yaml exec -T app npm run test:database
```

The integration test creates/drops only uniquely named owned temporary databases
on the two self-hosted servers; it does not select cloud. Rebuild the app image
when scripts/tests/package metadata change; source bind mounts alone do not
update those copied image files.

For the destructive-outage regression, **do not stop an attendee's databases**.
Run this from the repository root on a Docker host (including a disposable
Codespace terminal), not inside the app container:

```sh
npm run test:reconnect
```

Requires Docker Compose **2.24.4+** for its port override. It creates a fresh random
`ato-reconnect-*` project, private temporary `.env`, independent volumes and a
random **loopback-only** app port. It ignores ambient workshop credentials and
never adopts an existing project. It stops/starts only its Site B, captures
sanitized pass/fail receipts, and removes **only its own ephemeral project and
volumes** through a single idempotent cleanup path. **SIGINT / SIGTERM** abort
in-flight HTTP requests and probe waits, cancel child commands (with a five-second
force-termination grace), and enter that same cleanup path with a nonzero exit.
Repeated signals do not cancel cleanup. Its Compose deadline is 120 seconds;
each resource-inventory check has a 15-second deadline (plus termination grace).
The private directory is removed only after successful `down` and independent
empty inventories for the project's **containers, volumes and networks**.

Normal notebooks and `.env` are untouched. If cleanup or verification fails,
the process exits nonzero and retains its private configuration, printing only
the generated project name/private directory for manual review; it does not run
a global prune or claim success. SIGKILL, machine loss, or an unreachable Docker
daemon cannot guarantee cleanup. CI runs the normal regression as a separate
ephemeral job. The application runs directly without file watching in this
harness so checking its PID really establishes no app restart.

Opt-in interruption regression (Docker host, separate from the offline suite):

```sh
node --test test/reconnect-interruption.integration.js
```

This creates two fresh owned projects sequentially, sends SIGTERM and SIGINT
respectively after startup, repeats each signal during cleanup, and independently
checks nonzero handled exits, absent containers/volumes/networks, and removal of
only each run's private temporary directory. It does not stop an existing stack.

**Harness-only proof, October 17:** after adding handled-signal cleanup, the
normal live reconnect regression passed all five recovery/cleanup checks. The
real interruption test passed both SIGTERM (exit 143) and SIGINT (exit 130),
including repeated signals during cleanup. Independent filtered inventories
confirmed zero owned containers, volumes and networks and absent private
configuration directories for all three runs. These harness results do not
constitute another Codespace, browser, calendar or Azure acceptance run.

Then reopen/restart the actual attendee Codespace and follow [the lab](lab.md):
verify the friendly first screen, edit TODO 1, save TODO 2, inspect before/after,
optional query, Site A/B copying and calendar helper links in a real browser.
Offline UI mocks are not a rendered-browser acceptance test.

## Still unverified delivery gates

- A brand-new cold Codespace on this revision (the executed polish test restarted
the existing Codespace; the earlier 4m47s cold result remains scoped above).
- Fresh Organizer-profile acceptance (not required for attendees).
- Representative attendee accounts, quotas, resource needs, and conference
laptop/Wi-Fi networking; one two-core Codespace measurement is not capacity proof.
- Full **105-minute human classroom rehearsal**, including pairing fallback,
editing fluency, export and safe stopping.
- Approved existing-resource presenter rehearsal on the actual conference laptop
and network, and a verified backup recording.
- Apple Calendar GUI import and client-specific repeated-import handling.

The default attendee path remains Site A/B only. It never requires Azure,
Kubernetes, a laptop Docker installation, or automatic calendar API access.
Loading
Loading