Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2b30884
Unify Canadian regions with MeshMapper IATA scopes
n30nex Sep 25, 2026
8799f3e
Keep map controls readable when Leaflet styles load late
n30nex Sep 25, 2026
883bcc4
Merge remote-tracking branch 'origin/main' into codex/meshmapper-iata…
n30nex Sep 25, 2026
8115063
Add complementary IATA starter regions for Atlantic and northern gaps
n30nex Sep 25, 2026
44bf4c8
Complete Canada-wide IATA planning, migration checks and region revie…
n30nex Sep 25, 2026
fe98c36
Target the configurator action explicitly in region handoff tests
n30nex Sep 25, 2026
d74f4e9
Handle official French hamlet types and ambiguous Saint-Jean lookups
n30nex Sep 25, 2026
f13441b
Correct IATA gap boundaries using all regional centres
n30nex Sep 25, 2026
0ab52e6
Keep selected planning boundaries visually distinct
n30nex Sep 25, 2026
9e89b26
Merge current ON/QC rollout guidance without losing IATA fixes
n30nex Sep 25, 2026
32ae219
Merge PR #112 city and edge clarification into IATA scopes
n30nex Sep 25, 2026
71cdef8
Merge latest ON/QC guide updates from main
n30nex Sep 26, 2026
5c3d54b
Use the official MeshMapper zones API and fix map labels
n30nex Sep 26, 2026
9a8a594
Align companion guidance and configurator with ON/QC rollout phases
n30nex Sep 26, 2026
adbaf5a
Match region tools to the ON/QC proposal styling
n30nex Sep 26, 2026
3d269d9
Align map background regression with the shared palette
n30nex Sep 26, 2026
db5d5b0
Merge #114 reserved North America scope into IATA tools
n30nex Sep 26, 2026
c884465
Label proposal screenshots that predate the reserved na scope
n30nex Sep 26, 2026
c0e3054
Make ON/QC proposal settings discoverable for every listed region
n30nex Sep 26, 2026
8d23a21
feat: guide IATA preparation, coordinated activation and verification
n30nex Sep 27, 2026
f62970c
fix: reconfirm activation when proposal neighbours change
n30nex Sep 27, 2026
cb860cd
fix: distinguish preparation checks from unchanged-setting verification
n30nex Sep 27, 2026
fd6993d
test: isolate region journeys and stabilize WebKit worker allocation
n30nex Sep 27, 2026
6c7562e
fix: keep retained-scope uncertainty explicit in preparation examples
n30nex Sep 27, 2026
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
188 changes: 9 additions & 179 deletions .github/workflows/apply-approved-boundary.yml
Original file line number Diff line number Diff line change
@@ -1,189 +1,19 @@
name: Apply approved boundary update
name: Legacy census boundary application (retired)

# Closing an old boundary issue must never publish a competing census map.
on:
issues:
types: [closed]
workflow_dispatch:

permissions:
contents: read
issues: write

concurrency:
group: region-boundary-application
cancel-in-progress: false

jobs:
apply:
if: >-
github.event.issue.state_reason == 'completed' &&
contains(github.event.issue.labels.*.name, 'boundary-update')
retired:
runs-on: ubuntu-latest
timeout-minutes: 120
env:
GH_TOKEN: ${{ github.token }}
ISSUE_NUMBER: ${{ github.event.issue.number }}

timeout-minutes: 5
steps:
- name: Checkout current authority
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
ref: main
fetch-depth: 0
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: "3.13"

- name: Set up Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "22"

- name: Fetch proposal comments
shell: bash
run: |
set -euo pipefail
gh api --paginate --slurp \
"repos/$GITHUB_REPOSITORY/issues/$ISSUE_NUMBER/comments?per_page=100" \
> "$RUNNER_TEMP/issue-comments.json"

- name: Install submission verification key
shell: bash
env:
PUBLIC_KEY_PEM: ${{ secrets.MCC_SUBMISSION_PUBLIC_KEY_PEM }}
run: |
set -euo pipefail
test -n "$PUBLIC_KEY_PEM"
printf '%s\n' "$PUBLIC_KEY_PEM" > "$RUNNER_TEMP/submission-public-key.pem"
chmod 0600 "$RUNNER_TEMP/submission-public-key.pem"

- name: Verify approval and record reviewed decision
id: apply
shell: bash
run: |
set -euo pipefail
python scripts/apply-approved-region-issue.py \
--event "$GITHUB_EVENT_PATH" \
--comments "$RUNNER_TEMP/issue-comments.json" \
--public-key "$RUNNER_TEMP/submission-public-key.pem" \
--summary "$RUNNER_TEMP/boundary-application.json" \
--github-output "$GITHUB_OUTPUT"

- name: Fetch locked census sources
id: sources
if: steps.apply.outputs.already_applied != 'true'
shell: bash
run: |
set -euo pipefail
python scripts/fetch-locked-region-sources.py \
--cache-dir "$RUNNER_TEMP/region-sources" \
--github-output "$GITHUB_OUTPUT"

- name: Install region generator dependencies
if: steps.apply.outputs.already_applied != 'true'
run: |
python -m pip install -r scripts/requirements-regions.txt
python -m pip install -r tools/region-proposal-gateway/requirements.txt

- name: Materialize approved new regions
if: steps.apply.outputs.already_applied != 'true'
shell: bash
run: |
set -euo pipefail
python scripts/materialize-approved-new-regions.py \
--digital-da "${{ steps.sources.outputs.digital_da }}"

- name: Regenerate the national partition
if: steps.apply.outputs.already_applied != 'true'
env:
NODE_OPTIONS: --max-old-space-size=6144
shell: bash
run: |
set -euo pipefail
python scripts/generate-region-partition.py \
--digital-da "${{ steps.sources.outputs.digital_da }}" \
--cartographic-da "${{ steps.sources.outputs.cartographic_da }}" \
--economic-regions "${{ steps.sources.outputs.economic_regions }}" \
--census-divisions "${{ steps.sources.outputs.census_divisions }}" \
--census-subdivisions "${{ steps.sources.outputs.census_subdivisions }}"
python scripts/build-region-editor-data.py \
--digital-da "${{ steps.sources.outputs.digital_da }}" \
--census-subdivisions "${{ steps.sources.outputs.census_subdivisions }}" \
--census-divisions "${{ steps.sources.outputs.census_divisions }}" \
--membership docs/assets/regions/canada-region-membership.csv \
--catalog docs/assets/regions/canada-regions.json \
--retain 10% \
--output-dir docs/assets/regions/cells

- name: Validate regenerated authority
if: steps.apply.outputs.already_applied != 'true'
shell: bash
run: |
set -euo pipefail
node scripts/validate-regions.cjs
python scripts/verify-region-geometry.py
python scripts/verify-region-geometry.py \
--partition docs/assets/regions/canada-region-partition-digital.geojson
python -m unittest discover -s tools/region-proposal-gateway/tests -v
python -m unittest discover -s tests/automation -v
node --test tests/editor/*.test.mjs

- name: Publish approved authority
id: publish
if: steps.apply.outputs.already_applied != 'true'
shell: bash
env:
MCC_BOUNDARY_PUSH_TOKEN: ${{ secrets.MCC_BOUNDARY_PUSH_TOKEN }}
run: |
set -euo pipefail
if [[ -z "$MCC_BOUNDARY_PUSH_TOKEN" ]]; then
echo "MCC_BOUNDARY_PUSH_TOKEN is not configured." >&2
exit 1
fi
git diff --check
git add docs/assets/regions
if git diff --cached --quiet; then
echo "Approved proposal produced no authority change." >&2
exit 1
fi
git config user.name "MeshCore Canada Boundary Automation"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git commit -m "Apply boundary update #$ISSUE_NUMBER"
push_auth="$(printf 'x-access-token:%s' "$MCC_BOUNDARY_PUSH_TOKEN" | base64 -w0)"
echo "::add-mask::$push_auth"
git -c "http.https://github.com/.extraheader=AUTHORIZATION: basic $push_auth" \
push origin HEAD:main
unset push_auth MCC_BOUNDARY_PUSH_TOKEN
echo "commit_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
echo "APPLIED=1" >> "$GITHUB_ENV"

- name: Record successful application
shell: bash
run: |
set -euo pipefail
if [[ "${{ steps.apply.outputs.already_applied }}" == "true" ]]; then
message="This boundary update was already applied. No authority change was needed."
else
sha="${{ steps.publish.outputs.commit_sha }}"
message="Boundary update approved and applied in [\`${sha:0:7}\`](https://github.com/$GITHUB_REPOSITORY/commit/$sha). The push started the site deployment."
if [[ "${{ steps.apply.outputs.base_membership_matched }}" != "true" ]]; then
message="$message The map changed during review, so every requested cell was checked against its current owner before the update was applied."
fi
fi
gh issue comment "$ISSUE_NUMBER" --body "$message"

- name: Report a failed application
if: failure()
shell: bash
- name: Explain the replacement
run: |
set +e
if [[ "${APPLIED:-0}" == "1" ]]; then
gh issue comment "$ISSUE_NUMBER" --body \
"The boundary commit succeeded, but a follow-up step failed. Check this Action run and re-run the site deployment."
else
gh issue comment "$ISSUE_NUMBER" --body \
"The boundary update was not published because automated verification or regeneration failed. The issue has been reopened; check this Action run before approving it again."
gh issue reopen "$ISSUE_NUMBER"
fi
echo 'MeshMapper owns the current IATA zone boundaries.'
echo 'Legacy census-cell proposals are retained as history and are not applied.'
echo 'Review zone updates in MeshMapper, then refresh the repository snapshot through a PR.'
46 changes: 46 additions & 0 deletions .github/workflows/meshmapper-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Review MeshMapper changes
on:
schedule:
- cron: '23 14 * * 2'
workflow_dispatch:
permissions:
contents: read
issues: write
concurrency:
group: meshmapper-source-review
cancel-in-progress: false
jobs:
check:
# Scheduled review never runs code from an unmerged branch.
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: '22'
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: '3.13'
- name: Restore public API responses and ETags
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: .tmp/meshmapper-api-cache.json
key: ${{ runner.os }}-meshmapper-zones-v1-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: ${{ runner.os }}-meshmapper-zones-v1-
- name: Fetch the official zones API
run: node scripts/fetch-meshmapper-regions.mjs .tmp/meshmapper-review/candidate.geojson
- name: Check candidate geometry
run: |
python -m pip install shapely==2.0.6
python -c "import json; from shapely.geometry import shape, Point; data=json.load(open('.tmp/meshmapper-review/candidate.geojson')); assert all(shape(f['geometry']).is_valid and shape(f['geometry']).covers(Point(*f['properties']['center'])) for f in data['features'] if f['geometry'] is not None)"
- name: Prepare or update the review issue
env:
GITHUB_TOKEN: ${{ github.token }}
run: node scripts/check-meshmapper-changes.mjs .tmp/meshmapper-review/candidate.geojson --publish-issue
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: meshmapper-review
path: .tmp/meshmapper-review/
retention-days: 30
11 changes: 10 additions & 1 deletion .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ jobs:
- name: Validate region authority and proposal automation
run: |
node scripts/validate-regions.cjs
python scripts/verify-iata-geometry.py
node scripts/validate-legacy-region-data.cjs
python scripts/verify-region-geometry.py
python scripts/verify-region-geometry.py --partition docs/assets/regions/canada-region-partition-digital.geojson
python -m unittest discover -s tools/region-proposal-gateway/tests -v
Expand Down Expand Up @@ -99,16 +101,22 @@ jobs:
include:
- project: chromium
engine: chromium
workers: 4
- project: chromium-dark
engine: chromium
workers: 4
- project: mobile-chromium
engine: chromium
workers: 4
- project: firefox
engine: firefox
workers: 4
- project: webkit
engine: webkit
workers: 1
- project: mobile-webkit
engine: webkit
workers: 1

steps:
- name: Checkout repository
Expand Down Expand Up @@ -137,7 +145,8 @@ jobs:
run: npm run docs:build

- name: Run critical journeys and accessibility checks
run: npm run test:browser -- --project=${{ matrix.project }}
# WebKit gets a dedicated worker; keep action/test budgets unchanged.
run: npm run test:browser -- --project=${{ matrix.project }} --workers=${{ matrix.workers }}

# Branch protection requires a check named "browser"; this job passes only
# when every browser shard above passed.
Expand Down
41 changes: 39 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ Open `http://127.0.0.1:4173/`. Rebuild after editing. Build output belongs in
It generates the directory pages and `docs/assets/radio-profiles.json`.
Keep `data/community-search-anchors.json` in sync when adding listings. These
are approximate search references, not claimed radio locations or coverage.
- Region tools: `docs/assets/regions/` and `docs/config/editor/`.
Follow the boundary proposal workflow; do not hand-edit generated geography.
- Region tools: `docs/assets/regions/`, using published MeshMapper IATA zones
plus explicitly labelled MeshCore Canada starter regions.
Scope policy lives in `data/iata-scope-policy.json`. Follow the refresh steps
below; the former census boundary editor no longer accepts proposals.
- Broker settings: `docs/analyzer/observer-config.json`. The build generates the
broker reference table from this file, including its no-JavaScript version.
- Anonymous submissions: `tools/region-proposal-gateway/`. The site and gateway
Expand Down Expand Up @@ -69,6 +71,8 @@ For region, gateway, or automation changes, also run:
python -m pip install -r scripts/requirements-regions.txt
python -m pip install -r tools/region-proposal-gateway/requirements.txt
node scripts/validate-regions.cjs
python scripts/verify-iata-geometry.py
node scripts/validate-legacy-region-data.cjs
python scripts/verify-region-geometry.py
python scripts/verify-region-geometry.py --partition docs/assets/regions/canada-region-partition-digital.geojson
python -m unittest discover -s tools/region-proposal-gateway/tests
Expand All @@ -79,3 +83,36 @@ The quality workflow runs these checks on pull requests. Publishing is a separat
reviewed workflow; opening a PR does not authorize deploying it or changing brokers.
See [the September audit follow-up](maintenance/site-audit-2026-09-04.md) for the
current fixes, test coverage, and confirmations still needed from maintainers.

## Refresh MeshMapper zones

```sh
node scripts/fetch-meshmapper-regions.mjs .tmp/meshmapper-canada-current.geojson
```

Review the Canadian zone list and complete published polygons before replacing
`docs/assets/regions/meshmapper-iata-boundaries.geojson`. The importer fails if a
polygon is missing; do not substitute circles or nearest-airport areas. Update
`data/iata-scope-policy.json` for new/removed zones, then run:

```sh
python scripts/build-iata-boundaries.py
node scripts/build-iata-catalog.mjs
node scripts/validate-regions.cjs
python scripts/verify-iata-geometry.py
```

`iata-regions.json` and the compatibility URL `canada-regions.json` are identical
generated catalogues. `iata-boundaries.geojson` combines unchanged published zones
with the six starter assignments in `data/iata-starter-regions.json`.
`scope-jurisdictions.geojson` identifies the physical province and supplies broad
starter outlines; it does not alter MeshMapper boundaries. Labrador's outline
comes from official divisions 10 and 11, recorded in
`data/iata-labrador-outline.geojson`. To refresh that input, pass the SHA-256-locked
Statistics Canada CD ZIP to `python scripts/build-iata-boundaries.py --labrador-source <zip>`.
The generator subtracts published zones from starters and refuses a code collision;
review the starter's retirement when MeshMapper publishes the same code.
The old catalogue lives
in `maintenance/legacy-regions/` with its original geography retained for history.
See [the migration audit](maintenance/iata-scope-migration-2026-09-24.md) for scope
decisions, firmware support, migration risks, and deployment checks.
Loading
Loading