From 6a3b363dccc8b66dc27aed019efaa826e0b316b5 Mon Sep 17 00:00:00 2001 From: Scott Converse Date: Thu, 9 Jul 2026 21:32:38 -0600 Subject: [PATCH 1/2] brand: rename CivicClerk -> CivicMeetings (display layer) CivicPlus holds the registered CivicClerk(R) mark for a product in the same category (agenda/meeting management, acquired from BoardSync). Rename the module's public name to CivicMeetings before any public-facing push. Scope - brand layer only: - 483 display-form replacements across 140 living files (READMEs, USER-MANUAL, docs, UI strings, installer title, scripts, and the tests that pin doc text). - Machine identifiers unchanged: the `civicclerk` Python package, DB schema, CIVICCLERK_* env vars, and the /health service id. Existing installs and pinned consumers are unaffected. Identifier migration is deliberately deferred to the next release cascade. - 28 historical records intentionally keep the CivicClerk name they shipped under: ADRs, audit + browser-QA evidence packs, prior CHANGELOG entries, and the hash-bound v1.0.4 docs snapshot (docs/index.html). - CHANGELOG [Unreleased] and both READMEs disclose the rename. - GitHub repo renamed civicclerk -> civicmeetings (redirects active). Verified locally: full pytest = same pass/fail set as pristine main (the only run-to-run difference is a pre-existing flaky trio of timestamp-ordering persistence tests that flakes identically on pristine main; verified by 3x isolated runs on both branches). No workflow job ids or required check contexts changed. Co-Authored-By: Claude Fable 5 --- .../2026-06-10-capture-seq-determinism.md | 2 +- .../2026-06-10-clerk-persistence-phase-1.md | 6 +-- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/workflows/cleanroom.yml | 2 +- .github/workflows/release.yml | 10 ++-- .pipelines/civicclerk-release-plan.md | 6 +-- AGENTS.md | 10 ++-- CHANGELOG.md | 10 +++- CONTRIBUTING.md | 4 +- MILESTONE_0_DONE.md | 4 +- MILESTONE_10_DONE.md | 4 +- MILESTONE_11_DONE.md | 4 +- MILESTONE_12_DONE.md | 4 +- MILESTONE_1_DONE.md | 4 +- MILESTONE_2_DONE.md | 10 ++-- MILESTONE_6_DONE.md | 4 +- MILESTONE_7_DONE.md | 4 +- MILESTONE_8_DONE.md | 4 +- MILESTONE_9_DONE.md | 4 +- PRODUCTION_DEPTH_LIVE_ARCHIVE_SCREEN_DONE.md | 2 +- ...DEPTH_LIVE_CONNECTOR_IMPORT_SCREEN_DONE.md | 2 +- ...DEPTH_LIVE_MEETING_OUTCOMES_SCREEN_DONE.md | 2 +- ...ON_DEPTH_LIVE_MINUTES_DRAFT_SCREEN_DONE.md | 2 +- PRODUCTION_DEPTH_MEETING_PERSISTENCE_DONE.md | 2 +- PRODUCTION_DEPTH_PACKET_EXPORT_DONE.md | 2 +- README.md | 48 +++++++++-------- README.txt | 48 +++++++++-------- SECURITY.md | 2 +- SUPPORT.md | 2 +- TDD_LOG.md | 6 +-- USER-MANUAL.md | 42 +++++++-------- USER-MANUAL.txt | 42 +++++++-------- civicclerk/__init__.py | 2 +- civicclerk/agenda_lifecycle.py | 2 +- civicclerk/connectors.py | 2 +- civicclerk/demo_seed.py | 2 +- civicclerk/integration_contracts.py | 16 +++--- civicclerk/main.py | 54 +++++++++---------- civicclerk/meeting_lifecycle.py | 2 +- civicclerk/migrations/__init__.py | 2 +- civicclerk/migrations/alembic.ini | 2 +- civicclerk/migrations/env.py | 4 +- civicclerk/migrations/guards.py | 2 +- civicclerk/migrations/versions/__init__.py | 2 +- .../versions/civicclerk_0001_schema.py | 2 +- .../civicclerk_0011_data_model_completion.py | 2 +- civicclerk/minutes.py | 2 +- civicclerk/mock_city_environment.py | 18 +++---- civicclerk/models.py | 2 +- civicclerk/motion_vote.py | 2 +- civicclerk/oidc_auth.py | 16 +++--- civicclerk/packet_notice.py | 2 +- civicclerk/prompt_evals.py | 2 +- civicclerk/prompt_library.py | 6 +-- civicclerk/public_ui.py | 8 +-- civicclerk/staff_ui.py | 12 ++--- cleanroom/civicclerk.Dockerfile | 4 +- docs/MILESTONES.md | 10 ++-- docs/api/openapi.json | 8 +-- docs/architecture/ADR-0001-mvp-boundary.md | 4 +- docs/examples/deployment.env.example | 2 +- docs/examples/trusted-header-nginx.conf | 4 +- docs/frontend-staff-shell.md | 6 +-- docs/github-discussions-seed.md | 8 +-- docs/integration-depth-contracts.md | 14 ++--- docs/ops/cc-1-cleanroom-harness.md | 12 ++--- docs/ops/release-signing.md | 4 +- docs/ops/starter-set-integration.md | 12 ++--- docs/ops/tier1-retrofit-ledger.md | 4 +- docs/process/5-lens-self-audit.md | 2 +- docs/roadmap/mvp-plan.md | 8 +-- .../backup-restore-docs-summary.md | 2 +- .../cc1-cleanroom-freeze-summary.md | 2 +- docs/screenshots/v1-playwright-summary.md | 2 +- frontend/e2e/civicclerk-user-flows.spec.ts | 6 +-- frontend/index.html | 4 +- frontend/src/App.test.tsx | 6 +-- frontend/src/App.tsx | 20 +++---- install.ps1 | 14 ++--- installer/windows/README.md | 10 ++-- installer/windows/build-installer.sh | 2 +- installer/windows/civicclerk.iss | 30 +++++------ installer/windows/launch-start.ps1 | 2 +- installer/windows/prereq-check.ps1 | 4 +- prompts/minutes_draft.yaml | 2 +- prompts/staff_report_normalizer.yaml | 4 +- pyproject.toml | 2 +- scripts/build_release_handoff_bundle.ps1 | 2 +- scripts/build_release_handoff_bundle.sh | 4 +- .../check-civiccore-placeholder-imports.py | 2 +- scripts/check_backup_restore_rehearsal.py | 10 ++-- scripts/check_connector_sync_readiness.py | 6 +-- scripts/check_deployment_readiness.py | 6 +-- .../check_docker_backup_restore_rehearsal.py | 4 +- scripts/check_enterprise_installer_signing.py | 6 +-- scripts/check_installer_readiness.py | 10 ++-- scripts/check_pilot_readiness.py | 12 ++--- scripts/check_protected_deployment_smoke.py | 10 ++-- scripts/check_starter_set_integration.py | 40 +++++++------- scripts/check_vendor_live_sync_readiness.py | 6 +-- .../cleanroom/civicclerk-cleanroom-runner.sh | 2 +- scripts/generate-openapi-spec.py | 2 +- scripts/local_trusted_header_proxy.py | 10 ++-- scripts/run-civicclerk-cleanroom.sh | 6 +-- scripts/run-prompt-evals.py | 2 +- scripts/run_connector_import_sync.py | 6 +-- scripts/run_vendor_live_sync.py | 4 +- scripts/start_backup_restore_rehearsal.ps1 | 2 +- scripts/start_backup_restore_rehearsal.sh | 6 +-- .../start_docker_backup_restore_rehearsal.ps1 | 2 +- .../start_docker_backup_restore_rehearsal.sh | 2 +- scripts/start_fresh_install_rehearsal.ps1 | 8 +-- scripts/start_fresh_install_rehearsal.sh | 8 +-- scripts/verify-browser-qa.py | 2 +- scripts/verify-docs.sh | 2 +- scripts/verify-recovery-gates.py | 2 +- scripts/verify-release.sh | 2 +- tests/test_backup_restore_rehearsal_helper.py | 6 +-- .../test_civiccode_handoff_bearer_contract.py | 2 +- ...est_civiccode_handoff_emitter_real_wire.py | 2 +- tests/test_connector_import_sync_runner.py | 2 +- tests/test_connector_sync_readiness_helper.py | 2 +- tests/test_deployment_readiness_helper.py | 4 +- ..._docker_backup_restore_rehearsal_helper.py | 6 +-- tests/test_enterprise_installer_signing.py | 6 +-- tests/test_installer_readiness_helper.py | 2 +- tests/test_integration_depth_live.py | 2 +- tests/test_milestone_12_release.py | 4 +- tests/test_milestone_13_staff_workflow_ui.py | 6 +-- tests/test_milestone_1_runtime_foundation.py | 8 +-- .../test_milestone_2_schema_and_migrations.py | 2 +- tests/test_milestone_8_public_archive.py | 2 +- tests/test_milestone_9_prompt_yaml_evals.py | 2 +- tests/test_production_depth_staff_auth.py | 2 +- .../test_protected_deployment_smoke_helper.py | 6 +-- tests/test_public_portal_ui.py | 6 +-- tests/test_soft_ai_dependency.py | 2 +- tests/test_starter_set_integration_helper.py | 8 +-- tests/test_suite_session_bearer_contract.py | 2 +- tests/test_windows_installer_packaging.py | 12 ++--- 141 files changed, 488 insertions(+), 476 deletions(-) diff --git a/.claude/plans/2026-06-10-capture-seq-determinism.md b/.claude/plans/2026-06-10-capture-seq-determinism.md index e51b0c3..92515d2 100644 --- a/.claude/plans/2026-06-10-capture-seq-determinism.md +++ b/.claude/plans/2026-06-10-capture-seq-determinism.md @@ -2,7 +2,7 @@ **Date:** 2026-06-10 **Branch:** work/clerk-persistence-phase-1 -**Bug:** All four CivicClerk persistence repositories (`civicclerk/motion_vote.py`, +**Bug:** All four CivicMeetings persistence repositories (`civicclerk/motion_vote.py`, `civicclerk/minutes.py`, `civicclerk/public_archive.py`) order list reads by `(created_at, id)`. `id` is a random uuid4, so rows inserted within the same timestamp tick tiebreak randomly and insertion order is not preserved. diff --git a/.claude/plans/2026-06-10-clerk-persistence-phase-1.md b/.claude/plans/2026-06-10-clerk-persistence-phase-1.md index 1f834f1..7658fe8 100644 --- a/.claude/plans/2026-06-10-clerk-persistence-phase-1.md +++ b/.claude/plans/2026-06-10-clerk-persistence-phase-1.md @@ -1,4 +1,4 @@ -# CivicClerk Persistence Phase 1 Implementation Plan +# CivicMeetings Persistence Phase 1 Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. @@ -918,7 +918,7 @@ class MinutesDraftRepository: if not is_known_prompt_version(prompt_version): expected = expected_prompt_version_hint() return MinutesValidationError( - message="Minutes drafts must use a prompt version from the CivicClerk YAML prompt library.", + message="Minutes drafts must use a prompt version from the CivicMeetings YAML prompt library.", fix=f"Use prompt_version '{expected}' or another version returned by the prompt library.", ) @@ -2070,7 +2070,7 @@ Persistence Phase 1 update: motions, votes, action items, minutes drafts, public archive records, and resident comments now persist to the configured database when `CIVICCLERK_MOTION_VOTE_DB_URL`, `CIVICCLERK_MINUTES_DB_URL`, and `CIVICCLERK_PUBLIC_ARCHIVE_DB_URL` are set, so the legal record of a -meeting survives an API restart. Without those variables CivicClerk falls +meeting survives an API restart. Without those variables CivicMeetings falls back to in-memory stores and the legal record does not survive a restart — do not run a real public meeting without database-backed persistence enabled. Transcript records, ordinance/resolution handoffs, notice records, diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 4716b89..2c06242 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,6 @@ --- name: Bug report -about: Report a CivicClerk bug or documentation issue +about: Report a CivicMeetings bug or documentation issue title: "[Bug]: " labels: bug assignees: "" diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index cc95f35..1d94672 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,6 +1,6 @@ --- name: Feature request -about: Suggest a CivicClerk feature +about: Suggest a CivicMeetings feature title: "[Feature]: " labels: enhancement assignees: "" diff --git a/.github/workflows/cleanroom.yml b/.github/workflows/cleanroom.yml index dae7bcd..5abf0e5 100644 --- a/.github/workflows/cleanroom.yml +++ b/.github/workflows/cleanroom.yml @@ -44,7 +44,7 @@ jobs: path: civicclerk-cleanroom-${{ github.run_id }} - name: Verify Docker is available run: docker version - - name: Run CivicClerk cleanroom harness + - name: Run CivicMeetings cleanroom harness run: bash scripts/run-civicclerk-cleanroom.sh "$CC1_SHA" "docs/evidence/cc1-ci-${CC1_SHA}" - name: Upload cleanroom evidence uses: actions/upload-artifact@v7 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d1b9dee..a7eceb1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -72,7 +72,7 @@ jobs: expected = "${VERSION}" print(f"civicclerk.__version__={civicclerk.__version__}") if civicclerk.__version__ != expected: - raise SystemExit(f"Expected CivicClerk {expected}, got {civicclerk.__version__}") + raise SystemExit(f"Expected CivicMeetings {expected}, got {civicclerk.__version__}") print( "civiccore dependency import ok: " f"{CitedSentence.__name__}, {SourceMaterial.__name__}, {validate_cited_sentences.__name__}" @@ -242,7 +242,7 @@ jobs: export WHEEL_URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/civicclerk-${VERSION}-py3-none-any.whl" export CLEANROOM_TIMESTAMP="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" cat > release-notes.md < Formerly published as "CivicClerk"; renamed 2026-07 to avoid confusion with an unrelated commercial product of that name. Package and service identifiers are unchanged. -Status: CivicClerk v1.0.4 runtime foundation label is provisional during the CivicSuite release recovery. +**CivicMeetings is the CivicSuite module for municipal meetings, agendas, packets, minutes, votes, notices, and public meeting archives.** + +Status: CivicMeetings v1.0.4 runtime foundation label is provisional during the CivicSuite release recovery. Current version: `1.0.4` Repository: Depends on: published, Sigstore-attested `civiccore` 1.2.1 wheel from the `v1.2.1` release asset ## Release Recovery Notice -CivicClerk is not product-ready for public promotion while the CivicSuite +CivicMeetings is not product-ready for public promotion while the CivicSuite release recovery is active. Treat the current `v1.0.4` recovery patch as provisional until this repo re-earns release status through the recovery gates: full local backend tests, frontend unit tests, real Playwright user-flow @@ -29,7 +31,7 @@ with them — so the legal record of a meeting survives an API restart. The public archive database must also contain the published meeting's referent row in `civicclerk.meetings` (migration 0014); the publish endpoint returns a self-describing 404 with the fix when it does not. Without those -variables CivicClerk falls back to in-memory stores and the legal record +variables CivicMeetings falls back to in-memory stores and the legal record does not survive a restart — do not run a real public meeting without database-backed persistence enabled. Minutes adoption/posting write paths, transcript records, ordinance/resolution handoffs, posted notice records, @@ -37,10 +39,10 @@ and packet snapshots remain in-memory pending Persistence Phase 1b. ## Release Provenance -CivicClerk now wires the strengthened CivicCore release-provenance preflight +CivicMeetings now wires the strengthened CivicCore release-provenance preflight into release-class workflows. GitHub release pages can display a "Verified" badge for the target commit even when the release tag itself is lightweight or -unsigned, so CivicClerk treats that badge as a commit-only signal. Post-baseline +unsigned, so CivicMeetings treats that badge as a commit-only signal. Post-baseline releases are verified by a Sigstore-signed `release-attestation.json` plus bundle, and the exact verification shape lives in `docs/ops/release-signing.md`. @@ -50,9 +52,9 @@ include `release-attestation.json` or `release-attestation.json.bundle`. CO-4 records the decision in `docs/ops/tier1-retrofit-ledger.md`: do not delete, recreate, mirror, or promote `v0.1.20` as an attested provenance baseline. -## What CivicClerk will do +## What CivicMeetings will do -CivicClerk is designed for the legal record of public meetings: +CivicMeetings is designed for the legal record of public meetings: - agenda item intake from departments - packet assembly @@ -67,7 +69,7 @@ AI may draft or extract. Humans approve every consequential action. ## What exists today -CivicClerk currently contains the runtime and schema foundation plus database-backed agenda item lifecycle records, meeting lifecycle, packet snapshot, shared CivicCore-backed notice compliance, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public calendar/detail/archive endpoints, a prompt YAML library with an offline evaluation harness, local-first connector imports for Granicus, Legistar, PrimeGov, and NovusAGENDA, accessibility/browser QA gates, CivicCore v1.2.1-backed records export bundles, database-backed agenda intake readiness, database-backed packet assembly records, database-backed notice checklist/posting-proof records, database-backed meeting records, and first staff workflow screens for intake, packet assembly/export, notice checklist, meeting outcome, minutes draft, public archive, connector import, and vendor sync work. These capabilities remain under recovery validation and must not be promoted as product-ready until the recovery gates pass. The staff screens submit agenda intake, record readiness review, create/finalize packet assembly records, create records-ready packet export bundles, persist notice checklist records, attach posting proof, capture motions/votes/action items, create citation-gated minutes drafts, publish public-safe archive records, normalize local connector exports through the shared CivicCore connector import contract, surface vendor sync source health and no-network run logging, expose the shared CivicCore connector runtime validation helpers that future live-sync work can adopt without bespoke security plumbing, expose the first vendor live-sync readiness and circuit-breaker contract for future scheduled pulls, consume the shared CivicCore trusted-header config and proxy-source enforcement helpers, and expose `/staff/auth-readiness` so operators can verify whether OIDC, bearer, or trusted-header staff auth is deployment-ready before testing a live session. When OIDC, bearer, or trusted-header mode is ready, the readiness contract now includes a concrete protected-session probe and a protected-write probe instead of only env-var reminders, and trusted-header readiness now carries a loopback-only local proxy rehearsal contract that points operators to `scripts/local_trusted_header_proxy.py` with `127.0.0.1/32` as the safe starter allowlist. +CivicMeetings currently contains the runtime and schema foundation plus database-backed agenda item lifecycle records, meeting lifecycle, packet snapshot, shared CivicCore-backed notice compliance, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public calendar/detail/archive endpoints, a prompt YAML library with an offline evaluation harness, local-first connector imports for Granicus, Legistar, PrimeGov, and NovusAGENDA, accessibility/browser QA gates, CivicCore v1.2.1-backed records export bundles, database-backed agenda intake readiness, database-backed packet assembly records, database-backed notice checklist/posting-proof records, database-backed meeting records, and first staff workflow screens for intake, packet assembly/export, notice checklist, meeting outcome, minutes draft, public archive, connector import, and vendor sync work. These capabilities remain under recovery validation and must not be promoted as product-ready until the recovery gates pass. The staff screens submit agenda intake, record readiness review, create/finalize packet assembly records, create records-ready packet export bundles, persist notice checklist records, attach posting proof, capture motions/votes/action items, create citation-gated minutes drafts, publish public-safe archive records, normalize local connector exports through the shared CivicCore connector import contract, surface vendor sync source health and no-network run logging, expose the shared CivicCore connector runtime validation helpers that future live-sync work can adopt without bespoke security plumbing, expose the first vendor live-sync readiness and circuit-breaker contract for future scheduled pulls, consume the shared CivicCore trusted-header config and proxy-source enforcement helpers, and expose `/staff/auth-readiness` so operators can verify whether OIDC, bearer, or trusted-header staff auth is deployment-ready before testing a live session. When OIDC, bearer, or trusted-header mode is ready, the readiness contract now includes a concrete protected-session probe and a protected-write probe instead of only env-var reminders, and trusted-header readiness now carries a loopback-only local proxy rehearsal contract that points operators to `scripts/local_trusted_header_proxy.py` with `127.0.0.1/32` as the safe starter allowlist. Shipped in this foundation: @@ -97,7 +99,7 @@ Shipped in this foundation: promotion linkage via Alembic migrations `civicclerk_0002_intake_queue` and `civicclerk_0008_intake_promotion` - `/agenda-intake` submit/list/review/promote endpoints with audit events for consequential review and promotion actions -- canonical SQLAlchemy metadata for the fourteen CivicClerk tables +- canonical SQLAlchemy metadata for the fourteen CivicMeetings tables - Alembic scaffold and first idempotent migration for the `civicclerk` schema - CC-5 canonical data model completion through Alembic migration `civicclerk_0011_data_model`, adding downstream contract columns for packet @@ -265,7 +267,7 @@ Shipped in this foundation: | README data model claim | Verification | | --- | --- | -| All fourteen canonical CivicClerk tables remain present in the shared `civicclerk` schema. | `tests/test_milestone_2_schema_and_migrations.py::test_canonical_table_models_exist_and_no_tables_are_missing_or_extra` | +| All fourteen canonical CivicMeetings tables remain present in the shared `civicclerk` schema. | `tests/test_milestone_2_schema_and_migrations.py::test_canonical_table_models_exist_and_no_tables_are_missing_or_extra` | | `civicclerk_0011_data_model` upgrades, downgrades to the prior release head, and re-upgrades while preserving the packet-version contract. | `tests/test_milestone_2_schema_and_migrations.py::test_alembic_command_upgrades_real_pgvector_database`; `tests/test_milestone_2_schema_and_migrations.py::test_data_model_completion_migration_declares_reversible_cc5_contract` | | Packet snapshots are versioned per meeting by schema constraint. | `tests/test_milestone_2_schema_and_migrations.py::test_packet_versions_are_versioned_per_meeting_by_schema_contract` | | Motion and vote records carry append-only correction metadata that references the original record. | `tests/test_milestone_2_schema_and_migrations.py::test_motion_vote_canonical_tables_preserve_append_only_correction_contract`; `tests/test_milestone_6_motion_vote_action_capture.py::test_api_captured_motion_is_immutable_and_corrections_reference_original` | @@ -275,7 +277,7 @@ Shipped in this foundation: | README prompt claim | Verification | | --- | --- | -| Every spec-required CivicClerk prompt ships as versioned YAML and resolves through `civiccore.llm.resolve_template` under `consumer_app="civicclerk"`. | `tests/test_milestone_9_prompt_yaml_evals.py::test_all_spec_prompts_are_versioned_and_resolve_through_civiccore` | +| Every spec-required CivicMeetings prompt ships as versioned YAML and resolves through `civiccore.llm.resolve_template` under `consumer_app="civicclerk"`. | `tests/test_milestone_9_prompt_yaml_evals.py::test_all_spec_prompts_are_versioned_and_resolve_through_civiccore` | | The offline eval harness covers policy phrases, public approval gates, and input mutation stability without network calls. | `tests/test_milestone_9_prompt_yaml_evals.py::test_prompt_eval_harness_runs_offline_with_ollama_provider_selected` | | The eval harness uses the CivicCore resolver path instead of standalone prompt rendering. | `tests/test_milestone_9_prompt_yaml_evals.py::test_prompt_eval_harness_uses_civiccore_resolver_not_standalone_rendering` | - Docker Compose deployment stack with PostgreSQL 17 + pgvector, Redis 7.2, @@ -303,7 +305,7 @@ Shipped in this foundation: "Windows protected your PC" first-install experience, why this small free open-source project ships unsigned installers, and when it is OK to choose "More info" -> "Run anyway" -- CivicClerk v1.0.4 release gate and build artifacts +- CivicMeetings v1.0.4 release gate and build artifacts - `scripts/start_fresh_install_rehearsal.ps1` to rehearse the documented Windows-first wheel install and first-run smoke checks from an isolated `.fresh-install-rehearsal` virtual environment @@ -389,7 +391,7 @@ Not shipped yet: - city-specific live endpoint enablement for CivicRecords, CivicCode, CMS, codifier, or municipal Granicus/Legistar/PrimeGov/NovusAGENDA tenants. The - CivicClerk side now distinguishes live-wire or in-process boundary validation + CivicMeetings side now distinguishes live-wire or in-process boundary validation from supplemental adversarial mock regression checks, and real credentials plus endpoint activation remain a deployment task. @@ -428,7 +430,7 @@ A new user can inspect and run the foundation, open staff workflow screens at `/ - Expect Windows SmartScreen to show "Unknown Publisher" or "Windows protected your PC" because CivicSuite is a small free open-source project and the public installer is not signed with a paid publisher certificate. That warning is expected; choose "More info" and "Run anyway" only when the installer came from the official CivicSuite GitHub release source or your IT team built it from verified CivicSuite source. - Use `powershell -ExecutionPolicy Bypass -File scripts/build_release_handoff_bundle.ps1 -PrintOnly` on Windows PowerShell or `bash scripts/build_release_handoff_bundle.sh --print-only` on Linux, macOS, or Git Bash to preview the release handoff bundle, or rerun without the print-only flag after `bash scripts/verify-release.sh` has built `dist/` artifacts - Run `python scripts/check_installer_readiness.py` after creating the handoff bundle to verify installer input artifacts, checksums, docs, env examples, and rehearsal helpers before building or handing off the Windows setup package - - Run `python scripts/check_starter_set_integration.py --umbrella-root ..\civicsuite --require-archives` from this repo when verifying the CivicSuite starter-set package; it checks that CivicCore installs first, CivicRecords AI and CivicClerk are selectable, package workflow proof is required, and Linux/Windows archives exist + - Run `python scripts/check_starter_set_integration.py --umbrella-root ..\civicsuite --require-archives` from this repo when verifying the CivicSuite starter-set package; it checks that CivicCore installs first, CivicRecords AI and CivicMeetings are selectable, package workflow proof is required, and Linux/Windows archives exist - Run `python scripts/check_connector_sync_readiness.py` before vendor-network live-sync design work to prove the supported local connector payload contracts and optional future URL/ODBC guard checks without making vendor network calls - Run `python scripts/run_mock_city_environment_suite.py --output mock-city-report.json` to prove the reusable City of Brookfield vendor-interface and municipal IdP contract suite before adding module-specific integration assertions; this does not contact vendor networks or expose mock secrets - Run `python scripts/run_mock_city_environment_suite.py --hostile-mode --output mock-city-hostile-report.json` to prove the adversarial IdP, agenda-vendor, and backup-retention fixtures remain secret-free, no-network, and actionable before live city integration work begins @@ -457,7 +459,7 @@ A new user can inspect and run the foundation, open staff workflow screens at `/ - Use `powershell -ExecutionPolicy Bypass -File scripts/start_protected_demo_rehearsal.ps1 -PrintOnly` on Windows PowerShell or `bash scripts/start_protected_demo_rehearsal.sh --print-only` on Linux, macOS, or Git Bash to print the protected trusted-header demo profile before launching it 7. Exercise `/agenda-intake`, `/agenda-intake/{id}/review`, `/agenda-items`, `/agenda-items/{id}/transitions`, `/meetings`, `/meetings/{id}/transitions`, `/meetings/{id}/packet-snapshots`, `/meetings/{id}/packet-assemblies`, `/packet-assemblies/{id}/finalize`, `/meetings/{id}/notice-checklists`, `/notice-checklists/{id}/posting-proof`, `/meetings/{id}/export-bundle`, `/meetings/{id}/notices/post`, `/meetings/{id}/motions`, `/motions/{id}/votes`, `/meetings/{id}/action-items`, `/meetings/{id}/minutes/drafts`, `/meetings/{id}/public-record`, `/public/meetings`, `/public/archive/search`, `/imports/{connector}/meetings`, `/vendor-live-sync/sources`, `/vendor-live-sync/sources/{id}/run-log`, and `/vendor-live-sync/sources/{id}/cursor-reset` to smoke-check Milestone 10 plus the production-depth live staff action slices and the no-network vendor sync ledger. 8. Set `CIVICCLERK_AGENDA_ITEM_DB_URL` before agenda item lifecycle persistence smoke checks, set `CIVICCLERK_MEETING_DB_URL` before meeting persistence smoke checks, set `CIVICCLERK_VENDOR_SYNC_DB_URL` before durable vendor sync ledger smoke checks, and set `CIVICCLERK_EXPORT_ROOT` before API packet export smoke checks; API callers provide a relative `bundle_name`, not an arbitrary filesystem path. -9. In OIDC, bearer, or trusted-header mode, call `/staff/auth-readiness` first and use the returned `session_probe` plus `write_probe` before trusting a protected deployment. In OIDC mode, complete the browser-login settings and open `/staff/login`; CivicClerk redirects to the municipal provider with authorization-code + PKCE parameters, accepts the callback at `/staff/oidc/callback`, and stores a signed HttpOnly CivicClerk staff session cookie instead of storing the raw OIDC token in the browser. +9. In OIDC, bearer, or trusted-header mode, call `/staff/auth-readiness` first and use the returned `session_probe` plus `write_probe` before trusting a protected deployment. In OIDC mode, complete the browser-login settings and open `/staff/login`; CivicMeetings redirects to the municipal provider with authorization-code + PKCE parameters, accepts the callback at `/staff/oidc/callback`, and stores a signed HttpOnly CivicMeetings staff session cookie instead of storing the raw OIDC token in the browser. 10. If trusted-header mode is headed toward a real deployment, start from the returned `reverse_proxy_reference` block and the shipped `docs/examples/trusted-header-nginx.conf` sample before you wire in your real identity provider variables and TLS paths. 11. If trusted-header mode is still being rehearsed on one workstation, use the returned `local_proxy_rehearsal` block, set `CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES=127.0.0.1/32`, run `python scripts/local_trusted_header_proxy.py`, and browse the helper listen URL instead of the upstream app URL. 12. If you want the trusted-header demo profile without hand-exporting env vars on Windows PowerShell, run `powershell -ExecutionPolicy Bypass -File scripts/start_protected_demo_rehearsal.ps1 -PrintOnly` to print the exact commands, then rerun the same script without `-PrintOnly` to launch the app on `8877` and the helper proxy on `8878`. @@ -471,7 +473,7 @@ A new user can inspect and run the foundation, open staff workflow screens at `/ ## Architecture direction -CivicClerk follows the CivicSuite pattern: +CivicMeetings follows the CivicSuite pattern: - FastAPI backend - React frontend @@ -500,7 +502,7 @@ empty rehearsal database. The Windows installer package under The installer is unsigned, local-rehearsal oriented, and still requires Docker Desktop; use OIDC, bearer, or trusted-header auth before any shared deployment. -The foundation is intentionally thin. Canonical schema, Alembic scaffolding, agenda item lifecycle enforcement, agenda item lifecycle persistence, meeting lifecycle enforcement, meeting records, packet snapshot versioning, packet assembly records, notice checklist records, shared notice compliance enforcement, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public archive endpoints, prompt YAML/evaluation gates, local-first connector import normalization, browser QA gates, CivicClerk v1.0.4 release artifacts, and CivicCore v1.2.1 packet export, browser-evidence verification, connector runtime validation, and trusted-header config enforcement primitives are present. Minutes drafts require sentence-level citations, YAML prompt-version provenance, and human approval before acceptance, and they are never auto-adopted or auto-posted. Anonymous public archive endpoints do not reveal closed-session content in response bodies, counts, suggestions, or error messages. Connector imports record source provenance and do not require outbound network calls in the default local profile. The vendor live-sync foundation now validates proposed vendor source URLs without network calls, blocks credentials in URLs, persists source/run/failure state in `vendor_sync_sources`, `vendor_sync_run_log`, and `vendor_sync_failures`, computes source health as `healthy`, `degraded`, or `circuit_open`, persists `last_success_cursor_at`, plans connector-specific delta URLs from that cursor, advances it only after fully successful normalized pulls, and follows the CivicRecords AI circuit-breaker pattern of five consecutive full-run failures or two grace-period failures after unpause. Public packet exports block closed-session/restricted sources and include manifest, checksum, provenance, and audit evidence. Agenda item records now persist lifecycle status and CivicCore-verifiable transition audit hashes when `CIVICCLERK_AGENDA_ITEM_DB_URL` is configured, and ready agenda intake records can be promoted into those lifecycle records while preserving the generated agenda item id, promotion timestamp, and audit hash on the intake record. Meeting records now persist scheduled starts, meeting body ids, locations, normalized meeting type, lifecycle status, and CivicCore-verifiable transition and schedule-edit audit hashes when `CIVICCLERK_MEETING_DB_URL` is configured; schedule edits are allowed before the in-session lock point, write audit entries, and validate changed meeting body ids before accepting create/update requests. Vendor sync source, run, failure, and cursor state persist when `CIVICCLERK_VENDOR_SYNC_DB_URL` is configured; the API records operator state and no-network cursor resets without pulling vendors, while `scripts/run_vendor_live_sync.py` provides an explicitly enabled one-source pull runner that records outcomes in the same circuit-breaker ledger. Packet assembly records now persist source references, citations, linked packet snapshot ids, and durable audit hashes. Notice checklist records persist compliance outcomes, warnings, posting proof, and durable audit hashes. Browser QA now checks loading, success, empty, error, and partial states plus keyboard, focus, contrast, and console evidence, and release screenshots are bound to the current docs page through shared CivicCore verification helpers. CivicClerk v1.0.4 now pairs with the published `civiccore` 1.2.1 wheel from the `v1.2.1` release asset. The first staff auth foundation is now explicit: fresh installs default to `CIVICCLERK_STAFF_AUTH_MODE=protected` so anonymous staff writes are denied, local rehearsals can explicitly opt into `CIVICCLERK_STAFF_AUTH_MODE=open`, municipal identity-provider deployments can set `CIVICCLERK_STAFF_AUTH_MODE=oidc` plus issuer, audience, JWKS, role-claim, algorithm, authorization URL, token URL, client, redirect URI, and session-cookie-secret settings, bearer-protected pilots can set `CIVICCLERK_STAFF_AUTH_MODE=bearer` plus `CIVICCLERK_STAFF_AUTH_TOKEN_ROLES`, and trusted reverse-proxy deployments can set `CIVICCLERK_STAFF_AUTH_MODE=trusted_header` plus `CIVICCLERK_STAFF_SSO_PRINCIPAL_HEADER`, `CIVICCLERK_STAFF_SSO_ROLES_HEADER`, `CIVICCLERK_STAFF_SSO_PROVIDER`, and `CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES`. The `/staff/auth-readiness` endpoint now tells operators whether those OIDC token-validation, OIDC browser-login, bearer, or trusted-proxy settings are merely present or actually deployment-ready, and it includes a loopback-only rehearsal recipe so trusted-header testing does not require inventing a custom proxy first. +The foundation is intentionally thin. Canonical schema, Alembic scaffolding, agenda item lifecycle enforcement, agenda item lifecycle persistence, meeting lifecycle enforcement, meeting records, packet snapshot versioning, packet assembly records, notice checklist records, shared notice compliance enforcement, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public archive endpoints, prompt YAML/evaluation gates, local-first connector import normalization, browser QA gates, CivicMeetings v1.0.4 release artifacts, and CivicCore v1.2.1 packet export, browser-evidence verification, connector runtime validation, and trusted-header config enforcement primitives are present. Minutes drafts require sentence-level citations, YAML prompt-version provenance, and human approval before acceptance, and they are never auto-adopted or auto-posted. Anonymous public archive endpoints do not reveal closed-session content in response bodies, counts, suggestions, or error messages. Connector imports record source provenance and do not require outbound network calls in the default local profile. The vendor live-sync foundation now validates proposed vendor source URLs without network calls, blocks credentials in URLs, persists source/run/failure state in `vendor_sync_sources`, `vendor_sync_run_log`, and `vendor_sync_failures`, computes source health as `healthy`, `degraded`, or `circuit_open`, persists `last_success_cursor_at`, plans connector-specific delta URLs from that cursor, advances it only after fully successful normalized pulls, and follows the CivicRecords AI circuit-breaker pattern of five consecutive full-run failures or two grace-period failures after unpause. Public packet exports block closed-session/restricted sources and include manifest, checksum, provenance, and audit evidence. Agenda item records now persist lifecycle status and CivicCore-verifiable transition audit hashes when `CIVICCLERK_AGENDA_ITEM_DB_URL` is configured, and ready agenda intake records can be promoted into those lifecycle records while preserving the generated agenda item id, promotion timestamp, and audit hash on the intake record. Meeting records now persist scheduled starts, meeting body ids, locations, normalized meeting type, lifecycle status, and CivicCore-verifiable transition and schedule-edit audit hashes when `CIVICCLERK_MEETING_DB_URL` is configured; schedule edits are allowed before the in-session lock point, write audit entries, and validate changed meeting body ids before accepting create/update requests. Vendor sync source, run, failure, and cursor state persist when `CIVICCLERK_VENDOR_SYNC_DB_URL` is configured; the API records operator state and no-network cursor resets without pulling vendors, while `scripts/run_vendor_live_sync.py` provides an explicitly enabled one-source pull runner that records outcomes in the same circuit-breaker ledger. Packet assembly records now persist source references, citations, linked packet snapshot ids, and durable audit hashes. Notice checklist records persist compliance outcomes, warnings, posting proof, and durable audit hashes. Browser QA now checks loading, success, empty, error, and partial states plus keyboard, focus, contrast, and console evidence, and release screenshots are bound to the current docs page through shared CivicCore verification helpers. CivicMeetings v1.0.4 now pairs with the published `civiccore` 1.2.1 wheel from the `v1.2.1` release asset. The first staff auth foundation is now explicit: fresh installs default to `CIVICCLERK_STAFF_AUTH_MODE=protected` so anonymous staff writes are denied, local rehearsals can explicitly opt into `CIVICCLERK_STAFF_AUTH_MODE=open`, municipal identity-provider deployments can set `CIVICCLERK_STAFF_AUTH_MODE=oidc` plus issuer, audience, JWKS, role-claim, algorithm, authorization URL, token URL, client, redirect URI, and session-cookie-secret settings, bearer-protected pilots can set `CIVICCLERK_STAFF_AUTH_MODE=bearer` plus `CIVICCLERK_STAFF_AUTH_TOKEN_ROLES`, and trusted reverse-proxy deployments can set `CIVICCLERK_STAFF_AUTH_MODE=trusted_header` plus `CIVICCLERK_STAFF_SSO_PRINCIPAL_HEADER`, `CIVICCLERK_STAFF_SSO_ROLES_HEADER`, `CIVICCLERK_STAFF_SSO_PROVIDER`, and `CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES`. The `/staff/auth-readiness` endpoint now tells operators whether those OIDC token-validation, OIDC browser-login, bearer, or trusted-proxy settings are merely present or actually deployment-ready, and it includes a loopback-only rehearsal recipe so trusted-header testing does not require inventing a custom proxy first. The staff experience at `/staff` now includes a product cockpit plus first workflow screens for agenda intake, packet assembly/export, notice checklist/posting-proof, meeting outcome, minutes draft, public archive, connector import, and vendor sync work. It is intentionally honest: the cockpit gives clerks a day-at-a-glance desk, reads the live agenda intake queue for ready/pending/needs-revision counts, the Agenda Intake, Packet Assembly, Notice Checklist, Meeting Outcomes, Minutes Draft, and Vendor Sync panels render live queue/record rows with escaped user-submitted titles where applicable and actionable empty/unavailable-store rows, the workflow screens can submit their corresponding live API actions, the auth panel now renders concrete protected-session and protected-write probes from `/staff/auth-readiness` when OIDC, bearer, or trusted-header mode is ready, it surfaces the loopback-only local proxy rehearsal command and env vars when trusted-header mode is being staged, and the broader multi-role React clerk console is now beginning under `frontend/`. The React slice uses the CivicSuite mockup direction for a real staff shell, meeting body management, meeting scheduling, meeting calendar, lifecycle ribbon, audit/evidence drawer, pre-lock schedule editing, Agenda Intake submit/review/promotion, Packet Builder promoted-item selection, packet draft creation, per-meeting queue review, packet finalization, Notice Checklist statutory deadline review, legal-blocker copy, posting-proof attachment, immutable audit-hash evidence, Public Posting resident-safe list/detail/search, Meeting Outcomes motion/vote/action capture with immutable-record guidance, Minutes Draft source/citation/provenance capture, Vendor Sync source-health/circuit-breaker/cursor visibility with no-network run logging and full-reconciliation reset guidance, and no-dead-end QA states. The Docker profile now seeds Brookfield demo data so city IT can open the React app and see live work immediately; the unsigned Windows installer wraps that same stack for install/repair and daily start. The resident-facing `/public` route in the nginx product path now opens the React public portal directly, loads public calendar records, public-safe detail, and anonymous archive search from the live public APIs, and keeps restricted-session existence, counts, and summaries out of resident copy. @@ -520,10 +522,10 @@ For deployment hardening, `scripts/check_deployment_readiness.py` now prints a n ### CivicCode live handoff emitter -CivicClerk emits ordinance/resolution handoff records to CivicCode when the +CivicMeetings emits ordinance/resolution handoff records to CivicCode when the city-core installer or operator configures `CIVICCODE_INTAKE_URL` and the suite bearer handoff value. On successful -`POST /meetings/{meeting_id}/ordinance-resolution-handoff`, CivicClerk maps the +`POST /meetings/{meeting_id}/ordinance-resolution-handoff`, CivicMeetings maps the meeting, motion/agenda provenance, affected sections, source document reference, and adopted text into CivicCode's existing `/api/v1/civiccode/staff/civicclerk/ordinance-events` intake contract. The @@ -536,13 +538,13 @@ local handoff record always shows the result: - `EMIT_SKIPPED_UNCONFIGURED` when either required setting is missing. Retry failed or previously unconfigured records with -`POST /meetings/{meeting_id}/ordinance-resolution-handoff/retry`. CivicClerk does +`POST /meetings/{meeting_id}/ordinance-resolution-handoff/retry`. CivicMeetings does not run an infinite background retry loop; operators should fix the URL, shared value, or CivicCode health issue shown in the local record and then retry. For protected deployment smoke checks, `scripts/check_protected_deployment_smoke.py --env-file path\to\deployment.env` now loads the completed env profile, requires strict deployment readiness, verifies `/health` and `/staff/auth-readiness`, executes the readiness-provided protected session probe, executes the protected write probe, and redacts bearer tokens from output. Trusted-header profiles use `127.0.0.1` as the default in-process proxy source; pass `--trusted-proxy-client-ip` when the completed profile allowlists a different proxy test address. The sample profile intentionally fails this smoke until placeholders are replaced. -For local wheel backup/restore rehearsal, `scripts/check_backup_restore_rehearsal.py` creates a timestamped run under `.backup-restore-rehearsal`, seeds the SQLite-backed agenda intake, agenda item, meeting, packet assembly, and notice checklist stores, writes packet export evidence, copies those files into a backup directory with `civicclerk-backup-manifest.json`, restores them to separate `restored-data` and `restored-exports` directories, and reopens the restored records through CivicClerk repositories. Operators can preview the Windows-first wrapper with `powershell -ExecutionPolicy Bypass -File scripts/start_backup_restore_rehearsal.ps1 -PrintOnly` or the Bash wrapper with `bash scripts/start_backup_restore_rehearsal.sh --print-only`; failures name the file or record that did not survive and tell the operator to keep the run directory, fix the backup source or env var, and rerun with a new run id. +For local wheel backup/restore rehearsal, `scripts/check_backup_restore_rehearsal.py` creates a timestamped run under `.backup-restore-rehearsal`, seeds the SQLite-backed agenda intake, agenda item, meeting, packet assembly, and notice checklist stores, writes packet export evidence, copies those files into a backup directory with `civicclerk-backup-manifest.json`, restores them to separate `restored-data` and `restored-exports` directories, and reopens the restored records through CivicMeetings repositories. Operators can preview the Windows-first wrapper with `powershell -ExecutionPolicy Bypass -File scripts/start_backup_restore_rehearsal.ps1 -PrintOnly` or the Bash wrapper with `bash scripts/start_backup_restore_rehearsal.sh --print-only`; failures name the file or record that did not survive and tell the operator to keep the run directory, fix the backup source or env var, and rerun with a new run id. For Docker/PostgreSQL backup/restore rehearsal, `scripts/check_docker_backup_restore_rehearsal.py` works against the running Compose stack instead of the SQLite wheel stores. Operators can preview it with `powershell -ExecutionPolicy Bypass -File scripts/start_docker_backup_restore_rehearsal.ps1 -PrintOnly` or `bash scripts/start_docker_backup_restore_rehearsal.sh --print-only`; rerunning without the print-only flag creates `.docker-backup-restore-rehearsal`, uses `pg_dump` to write `backup/civicclerk-postgres.dump`, creates a temporary restore database, runs `pg_restore`, records restored application tables in `restore-verification.json`, writes `backup/civicclerk-docker-backup-manifest.json`, and drops the temporary restore database by default. It does not drop, clean, or overwrite the source `civicclerk` database. diff --git a/README.txt b/README.txt index 32688b3..0e60991 100644 --- a/README.txt +++ b/README.txt @@ -1,15 +1,17 @@ -# CivicClerk +# CivicMeetings -**CivicClerk is the CivicSuite module for municipal meetings, agendas, packets, minutes, votes, notices, and public meeting archives.** +> Formerly published as "CivicClerk"; renamed 2026-07 to avoid confusion with an unrelated commercial product of that name. Package and service identifiers are unchanged. -Status: CivicClerk v1.0.4 runtime foundation label is provisional during the CivicSuite release recovery. +**CivicMeetings is the CivicSuite module for municipal meetings, agendas, packets, minutes, votes, notices, and public meeting archives.** + +Status: CivicMeetings v1.0.4 runtime foundation label is provisional during the CivicSuite release recovery. Current version: `1.0.4` Repository: Depends on: published, Sigstore-attested `civiccore` 1.2.1 wheel from the `v1.2.1` release asset ## Release Recovery Notice -CivicClerk is not product-ready for public promotion while the CivicSuite +CivicMeetings is not product-ready for public promotion while the CivicSuite release recovery is active. Treat the current `v1.0.4` recovery patch as provisional until this repo re-earns release status through the recovery gates: full local backend tests, frontend unit tests, real Playwright user-flow @@ -29,7 +31,7 @@ with them — so the legal record of a meeting survives an API restart. The public archive database must also contain the published meeting's referent row in `civicclerk.meetings` (migration 0014); the publish endpoint returns a self-describing 404 with the fix when it does not. Without those -variables CivicClerk falls back to in-memory stores and the legal record +variables CivicMeetings falls back to in-memory stores and the legal record does not survive a restart — do not run a real public meeting without database-backed persistence enabled. Minutes adoption/posting write paths, transcript records, ordinance/resolution handoffs, posted notice records, @@ -37,10 +39,10 @@ and packet snapshots remain in-memory pending Persistence Phase 1b. ## Release Provenance -CivicClerk now wires the strengthened CivicCore release-provenance preflight +CivicMeetings now wires the strengthened CivicCore release-provenance preflight into release-class workflows. GitHub release pages can display a "Verified" badge for the target commit even when the release tag itself is lightweight or -unsigned, so CivicClerk treats that badge as a commit-only signal. Post-baseline +unsigned, so CivicMeetings treats that badge as a commit-only signal. Post-baseline releases are verified by a Sigstore-signed `release-attestation.json` plus bundle, and the exact verification shape lives in `docs/ops/release-signing.md`. @@ -50,9 +52,9 @@ include `release-attestation.json` or `release-attestation.json.bundle`. CO-4 records the decision in `docs/ops/tier1-retrofit-ledger.md`: do not delete, recreate, mirror, or promote `v0.1.20` as an attested provenance baseline. -## What CivicClerk will do +## What CivicMeetings will do -CivicClerk is designed for the legal record of public meetings: +CivicMeetings is designed for the legal record of public meetings: - agenda item intake from departments - packet assembly @@ -67,7 +69,7 @@ AI may draft or extract. Humans approve every consequential action. ## What exists today -CivicClerk currently contains the runtime and schema foundation plus database-backed agenda item lifecycle records, meeting lifecycle, packet snapshot, shared CivicCore-backed notice compliance, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public calendar/detail/archive endpoints, a prompt YAML library with an offline evaluation harness, local-first connector imports for Granicus, Legistar, PrimeGov, and NovusAGENDA, accessibility/browser QA gates, CivicCore v1.2.1-backed records export bundles, database-backed agenda intake readiness, database-backed packet assembly records, database-backed notice checklist/posting-proof records, database-backed meeting records, and first staff workflow screens for intake, packet assembly/export, notice checklist, meeting outcome, minutes draft, public archive, connector import, and vendor sync work. These capabilities remain under recovery validation and must not be promoted as product-ready until the recovery gates pass. The staff screens submit agenda intake, record readiness review, create/finalize packet assembly records, create records-ready packet export bundles, persist notice checklist records, attach posting proof, capture motions/votes/action items, create citation-gated minutes drafts, publish public-safe archive records, normalize local connector exports through the shared CivicCore connector import contract, surface vendor sync source health and no-network run logging, expose the shared CivicCore connector runtime validation helpers that future live-sync work can adopt without bespoke security plumbing, expose the first vendor live-sync readiness and circuit-breaker contract for future scheduled pulls, consume the shared CivicCore trusted-header config and proxy-source enforcement helpers, and expose `/staff/auth-readiness` so operators can verify whether OIDC, bearer, or trusted-header staff auth is deployment-ready before testing a live session. When OIDC, bearer, or trusted-header mode is ready, the readiness contract now includes a concrete protected-session probe and a protected-write probe instead of only env-var reminders, and trusted-header readiness now carries a loopback-only local proxy rehearsal contract that points operators to `scripts/local_trusted_header_proxy.py` with `127.0.0.1/32` as the safe starter allowlist. +CivicMeetings currently contains the runtime and schema foundation plus database-backed agenda item lifecycle records, meeting lifecycle, packet snapshot, shared CivicCore-backed notice compliance, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public calendar/detail/archive endpoints, a prompt YAML library with an offline evaluation harness, local-first connector imports for Granicus, Legistar, PrimeGov, and NovusAGENDA, accessibility/browser QA gates, CivicCore v1.2.1-backed records export bundles, database-backed agenda intake readiness, database-backed packet assembly records, database-backed notice checklist/posting-proof records, database-backed meeting records, and first staff workflow screens for intake, packet assembly/export, notice checklist, meeting outcome, minutes draft, public archive, connector import, and vendor sync work. These capabilities remain under recovery validation and must not be promoted as product-ready until the recovery gates pass. The staff screens submit agenda intake, record readiness review, create/finalize packet assembly records, create records-ready packet export bundles, persist notice checklist records, attach posting proof, capture motions/votes/action items, create citation-gated minutes drafts, publish public-safe archive records, normalize local connector exports through the shared CivicCore connector import contract, surface vendor sync source health and no-network run logging, expose the shared CivicCore connector runtime validation helpers that future live-sync work can adopt without bespoke security plumbing, expose the first vendor live-sync readiness and circuit-breaker contract for future scheduled pulls, consume the shared CivicCore trusted-header config and proxy-source enforcement helpers, and expose `/staff/auth-readiness` so operators can verify whether OIDC, bearer, or trusted-header staff auth is deployment-ready before testing a live session. When OIDC, bearer, or trusted-header mode is ready, the readiness contract now includes a concrete protected-session probe and a protected-write probe instead of only env-var reminders, and trusted-header readiness now carries a loopback-only local proxy rehearsal contract that points operators to `scripts/local_trusted_header_proxy.py` with `127.0.0.1/32` as the safe starter allowlist. Shipped in this foundation: @@ -97,7 +99,7 @@ Shipped in this foundation: promotion linkage via Alembic migrations `civicclerk_0002_intake_queue` and `civicclerk_0008_intake_promotion` - `/agenda-intake` submit/list/review/promote endpoints with audit events for consequential review and promotion actions -- canonical SQLAlchemy metadata for the fourteen CivicClerk tables +- canonical SQLAlchemy metadata for the fourteen CivicMeetings tables - Alembic scaffold and first idempotent migration for the `civicclerk` schema - CC-5 canonical data model completion through Alembic migration `civicclerk_0011_data_model`, adding downstream contract columns for packet @@ -265,7 +267,7 @@ Shipped in this foundation: | README data model claim | Verification | | --- | --- | -| All fourteen canonical CivicClerk tables remain present in the shared `civicclerk` schema. | `tests/test_milestone_2_schema_and_migrations.py::test_canonical_table_models_exist_and_no_tables_are_missing_or_extra` | +| All fourteen canonical CivicMeetings tables remain present in the shared `civicclerk` schema. | `tests/test_milestone_2_schema_and_migrations.py::test_canonical_table_models_exist_and_no_tables_are_missing_or_extra` | | `civicclerk_0011_data_model` upgrades, downgrades to the prior release head, and re-upgrades while preserving the packet-version contract. | `tests/test_milestone_2_schema_and_migrations.py::test_alembic_command_upgrades_real_pgvector_database`; `tests/test_milestone_2_schema_and_migrations.py::test_data_model_completion_migration_declares_reversible_cc5_contract` | | Packet snapshots are versioned per meeting by schema constraint. | `tests/test_milestone_2_schema_and_migrations.py::test_packet_versions_are_versioned_per_meeting_by_schema_contract` | | Motion and vote records carry append-only correction metadata that references the original record. | `tests/test_milestone_2_schema_and_migrations.py::test_motion_vote_canonical_tables_preserve_append_only_correction_contract`; `tests/test_milestone_6_motion_vote_action_capture.py::test_api_captured_motion_is_immutable_and_corrections_reference_original` | @@ -275,7 +277,7 @@ Shipped in this foundation: | README prompt claim | Verification | | --- | --- | -| Every spec-required CivicClerk prompt ships as versioned YAML and resolves through `civiccore.llm.resolve_template` under `consumer_app="civicclerk"`. | `tests/test_milestone_9_prompt_yaml_evals.py::test_all_spec_prompts_are_versioned_and_resolve_through_civiccore` | +| Every spec-required CivicMeetings prompt ships as versioned YAML and resolves through `civiccore.llm.resolve_template` under `consumer_app="civicclerk"`. | `tests/test_milestone_9_prompt_yaml_evals.py::test_all_spec_prompts_are_versioned_and_resolve_through_civiccore` | | The offline eval harness covers policy phrases, public approval gates, and input mutation stability without network calls. | `tests/test_milestone_9_prompt_yaml_evals.py::test_prompt_eval_harness_runs_offline_with_ollama_provider_selected` | | The eval harness uses the CivicCore resolver path instead of standalone prompt rendering. | `tests/test_milestone_9_prompt_yaml_evals.py::test_prompt_eval_harness_uses_civiccore_resolver_not_standalone_rendering` | - Docker Compose deployment stack with PostgreSQL 17 + pgvector, Redis 7.2, @@ -303,7 +305,7 @@ Shipped in this foundation: "Windows protected your PC" first-install experience, why this small free open-source project ships unsigned installers, and when it is OK to choose "More info" -> "Run anyway" -- CivicClerk v1.0.4 release gate and build artifacts +- CivicMeetings v1.0.4 release gate and build artifacts - `scripts/start_fresh_install_rehearsal.ps1` to rehearse the documented Windows-first wheel install and first-run smoke checks from an isolated `.fresh-install-rehearsal` virtual environment @@ -389,7 +391,7 @@ Not shipped yet: - city-specific live endpoint enablement for CivicRecords, CivicCode, CMS, codifier, or municipal Granicus/Legistar/PrimeGov/NovusAGENDA tenants. The - CivicClerk side now distinguishes live-wire or in-process boundary validation + CivicMeetings side now distinguishes live-wire or in-process boundary validation from supplemental adversarial mock regression checks, and real credentials plus endpoint activation remain a deployment task. @@ -428,7 +430,7 @@ A new user can inspect and run the foundation, open staff workflow screens at `/ - Expect Windows SmartScreen to show "Unknown Publisher" or "Windows protected your PC" because CivicSuite is a small free open-source project and the public installer is not signed with a paid publisher certificate. That warning is expected; choose "More info" and "Run anyway" only when the installer came from the official CivicSuite GitHub release source or your IT team built it from verified CivicSuite source. - Use `powershell -ExecutionPolicy Bypass -File scripts/build_release_handoff_bundle.ps1 -PrintOnly` on Windows PowerShell or `bash scripts/build_release_handoff_bundle.sh --print-only` on Linux, macOS, or Git Bash to preview the release handoff bundle, or rerun without the print-only flag after `bash scripts/verify-release.sh` has built `dist/` artifacts - Run `python scripts/check_installer_readiness.py` after creating the handoff bundle to verify installer input artifacts, checksums, docs, env examples, and rehearsal helpers before building or handing off the Windows setup package - - Run `python scripts/check_starter_set_integration.py --umbrella-root ..\civicsuite --require-archives` from this repo when verifying the CivicSuite starter-set package; it checks that CivicCore installs first, CivicRecords AI and CivicClerk are selectable, package workflow proof is required, and Linux/Windows archives exist + - Run `python scripts/check_starter_set_integration.py --umbrella-root ..\civicsuite --require-archives` from this repo when verifying the CivicSuite starter-set package; it checks that CivicCore installs first, CivicRecords AI and CivicMeetings are selectable, package workflow proof is required, and Linux/Windows archives exist - Run `python scripts/check_connector_sync_readiness.py` before vendor-network live-sync design work to prove the supported local connector payload contracts and optional future URL/ODBC guard checks without making vendor network calls - Run `python scripts/run_mock_city_environment_suite.py --output mock-city-report.json` to prove the reusable City of Brookfield vendor-interface and municipal IdP contract suite before adding module-specific integration assertions; this does not contact vendor networks or expose mock secrets - Run `python scripts/run_mock_city_environment_suite.py --hostile-mode --output mock-city-hostile-report.json` to prove the adversarial IdP, agenda-vendor, and backup-retention fixtures remain secret-free, no-network, and actionable before live city integration work begins @@ -457,7 +459,7 @@ A new user can inspect and run the foundation, open staff workflow screens at `/ - Use `powershell -ExecutionPolicy Bypass -File scripts/start_protected_demo_rehearsal.ps1 -PrintOnly` on Windows PowerShell or `bash scripts/start_protected_demo_rehearsal.sh --print-only` on Linux, macOS, or Git Bash to print the protected trusted-header demo profile before launching it 7. Exercise `/agenda-intake`, `/agenda-intake/{id}/review`, `/agenda-items`, `/agenda-items/{id}/transitions`, `/meetings`, `/meetings/{id}/transitions`, `/meetings/{id}/packet-snapshots`, `/meetings/{id}/packet-assemblies`, `/packet-assemblies/{id}/finalize`, `/meetings/{id}/notice-checklists`, `/notice-checklists/{id}/posting-proof`, `/meetings/{id}/export-bundle`, `/meetings/{id}/notices/post`, `/meetings/{id}/motions`, `/motions/{id}/votes`, `/meetings/{id}/action-items`, `/meetings/{id}/minutes/drafts`, `/meetings/{id}/public-record`, `/public/meetings`, `/public/archive/search`, `/imports/{connector}/meetings`, `/vendor-live-sync/sources`, `/vendor-live-sync/sources/{id}/run-log`, and `/vendor-live-sync/sources/{id}/cursor-reset` to smoke-check Milestone 10 plus the production-depth live staff action slices and the no-network vendor sync ledger. 8. Set `CIVICCLERK_AGENDA_ITEM_DB_URL` before agenda item lifecycle persistence smoke checks, set `CIVICCLERK_MEETING_DB_URL` before meeting persistence smoke checks, set `CIVICCLERK_VENDOR_SYNC_DB_URL` before durable vendor sync ledger smoke checks, and set `CIVICCLERK_EXPORT_ROOT` before API packet export smoke checks; API callers provide a relative `bundle_name`, not an arbitrary filesystem path. -9. In OIDC, bearer, or trusted-header mode, call `/staff/auth-readiness` first and use the returned `session_probe` plus `write_probe` before trusting a protected deployment. In OIDC mode, complete the browser-login settings and open `/staff/login`; CivicClerk redirects to the municipal provider with authorization-code + PKCE parameters, accepts the callback at `/staff/oidc/callback`, and stores a signed HttpOnly CivicClerk staff session cookie instead of storing the raw OIDC token in the browser. +9. In OIDC, bearer, or trusted-header mode, call `/staff/auth-readiness` first and use the returned `session_probe` plus `write_probe` before trusting a protected deployment. In OIDC mode, complete the browser-login settings and open `/staff/login`; CivicMeetings redirects to the municipal provider with authorization-code + PKCE parameters, accepts the callback at `/staff/oidc/callback`, and stores a signed HttpOnly CivicMeetings staff session cookie instead of storing the raw OIDC token in the browser. 10. If trusted-header mode is headed toward a real deployment, start from the returned `reverse_proxy_reference` block and the shipped `docs/examples/trusted-header-nginx.conf` sample before you wire in your real identity provider variables and TLS paths. 11. If trusted-header mode is still being rehearsed on one workstation, use the returned `local_proxy_rehearsal` block, set `CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES=127.0.0.1/32`, run `python scripts/local_trusted_header_proxy.py`, and browse the helper listen URL instead of the upstream app URL. 12. If you want the trusted-header demo profile without hand-exporting env vars on Windows PowerShell, run `powershell -ExecutionPolicy Bypass -File scripts/start_protected_demo_rehearsal.ps1 -PrintOnly` to print the exact commands, then rerun the same script without `-PrintOnly` to launch the app on `8877` and the helper proxy on `8878`. @@ -471,7 +473,7 @@ A new user can inspect and run the foundation, open staff workflow screens at `/ ## Architecture direction -CivicClerk follows the CivicSuite pattern: +CivicMeetings follows the CivicSuite pattern: - FastAPI backend - React frontend @@ -500,7 +502,7 @@ empty rehearsal database. The Windows installer package under The installer is unsigned, local-rehearsal oriented, and still requires Docker Desktop; use OIDC, bearer, or trusted-header auth before any shared deployment. -The foundation is intentionally thin. Canonical schema, Alembic scaffolding, agenda item lifecycle enforcement, agenda item lifecycle persistence, meeting lifecycle enforcement, meeting records, packet snapshot versioning, packet assembly records, notice checklist records, shared notice compliance enforcement, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public archive endpoints, prompt YAML/evaluation gates, local-first connector import normalization, browser QA gates, CivicClerk v1.0.4 release artifacts, and CivicCore v1.2.1 packet export, browser-evidence verification, connector runtime validation, and trusted-header config enforcement primitives are present. Minutes drafts require sentence-level citations, YAML prompt-version provenance, and human approval before acceptance, and they are never auto-adopted or auto-posted. Anonymous public archive endpoints do not reveal closed-session content in response bodies, counts, suggestions, or error messages. Connector imports record source provenance and do not require outbound network calls in the default local profile. The vendor live-sync foundation now validates proposed vendor source URLs without network calls, blocks credentials in URLs, persists source/run/failure state in `vendor_sync_sources`, `vendor_sync_run_log`, and `vendor_sync_failures`, computes source health as `healthy`, `degraded`, or `circuit_open`, persists `last_success_cursor_at`, plans connector-specific delta URLs from that cursor, advances it only after fully successful normalized pulls, and follows the CivicRecords AI circuit-breaker pattern of five consecutive full-run failures or two grace-period failures after unpause. Public packet exports block closed-session/restricted sources and include manifest, checksum, provenance, and audit evidence. Agenda item records now persist lifecycle status and CivicCore-verifiable transition audit hashes when `CIVICCLERK_AGENDA_ITEM_DB_URL` is configured, and ready agenda intake records can be promoted into those lifecycle records while preserving the generated agenda item id, promotion timestamp, and audit hash on the intake record. Meeting records now persist scheduled starts, meeting body ids, locations, normalized meeting type, lifecycle status, and CivicCore-verifiable transition and schedule-edit audit hashes when `CIVICCLERK_MEETING_DB_URL` is configured; schedule edits are allowed before the in-session lock point, write audit entries, and validate changed meeting body ids before accepting create/update requests. Vendor sync source, run, failure, and cursor state persist when `CIVICCLERK_VENDOR_SYNC_DB_URL` is configured; the API records operator state and no-network cursor resets without pulling vendors, while `scripts/run_vendor_live_sync.py` provides an explicitly enabled one-source pull runner that records outcomes in the same circuit-breaker ledger. Packet assembly records now persist source references, citations, linked packet snapshot ids, and durable audit hashes. Notice checklist records persist compliance outcomes, warnings, posting proof, and durable audit hashes. Browser QA now checks loading, success, empty, error, and partial states plus keyboard, focus, contrast, and console evidence, and release screenshots are bound to the current docs page through shared CivicCore verification helpers. CivicClerk v1.0.4 now pairs with the published `civiccore` 1.2.1 wheel from the `v1.2.1` release asset. The first staff auth foundation is now explicit: fresh installs default to `CIVICCLERK_STAFF_AUTH_MODE=protected` so anonymous staff writes are denied, local rehearsals can explicitly opt into `CIVICCLERK_STAFF_AUTH_MODE=open`, municipal identity-provider deployments can set `CIVICCLERK_STAFF_AUTH_MODE=oidc` plus issuer, audience, JWKS, role-claim, algorithm, authorization URL, token URL, client, redirect URI, and session-cookie-secret settings, bearer-protected pilots can set `CIVICCLERK_STAFF_AUTH_MODE=bearer` plus `CIVICCLERK_STAFF_AUTH_TOKEN_ROLES`, and trusted reverse-proxy deployments can set `CIVICCLERK_STAFF_AUTH_MODE=trusted_header` plus `CIVICCLERK_STAFF_SSO_PRINCIPAL_HEADER`, `CIVICCLERK_STAFF_SSO_ROLES_HEADER`, `CIVICCLERK_STAFF_SSO_PROVIDER`, and `CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES`. The `/staff/auth-readiness` endpoint now tells operators whether those OIDC token-validation, OIDC browser-login, bearer, or trusted-proxy settings are merely present or actually deployment-ready, and it includes a loopback-only rehearsal recipe so trusted-header testing does not require inventing a custom proxy first. +The foundation is intentionally thin. Canonical schema, Alembic scaffolding, agenda item lifecycle enforcement, agenda item lifecycle persistence, meeting lifecycle enforcement, meeting records, packet snapshot versioning, packet assembly records, notice checklist records, shared notice compliance enforcement, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public archive endpoints, prompt YAML/evaluation gates, local-first connector import normalization, browser QA gates, CivicMeetings v1.0.4 release artifacts, and CivicCore v1.2.1 packet export, browser-evidence verification, connector runtime validation, and trusted-header config enforcement primitives are present. Minutes drafts require sentence-level citations, YAML prompt-version provenance, and human approval before acceptance, and they are never auto-adopted or auto-posted. Anonymous public archive endpoints do not reveal closed-session content in response bodies, counts, suggestions, or error messages. Connector imports record source provenance and do not require outbound network calls in the default local profile. The vendor live-sync foundation now validates proposed vendor source URLs without network calls, blocks credentials in URLs, persists source/run/failure state in `vendor_sync_sources`, `vendor_sync_run_log`, and `vendor_sync_failures`, computes source health as `healthy`, `degraded`, or `circuit_open`, persists `last_success_cursor_at`, plans connector-specific delta URLs from that cursor, advances it only after fully successful normalized pulls, and follows the CivicRecords AI circuit-breaker pattern of five consecutive full-run failures or two grace-period failures after unpause. Public packet exports block closed-session/restricted sources and include manifest, checksum, provenance, and audit evidence. Agenda item records now persist lifecycle status and CivicCore-verifiable transition audit hashes when `CIVICCLERK_AGENDA_ITEM_DB_URL` is configured, and ready agenda intake records can be promoted into those lifecycle records while preserving the generated agenda item id, promotion timestamp, and audit hash on the intake record. Meeting records now persist scheduled starts, meeting body ids, locations, normalized meeting type, lifecycle status, and CivicCore-verifiable transition and schedule-edit audit hashes when `CIVICCLERK_MEETING_DB_URL` is configured; schedule edits are allowed before the in-session lock point, write audit entries, and validate changed meeting body ids before accepting create/update requests. Vendor sync source, run, failure, and cursor state persist when `CIVICCLERK_VENDOR_SYNC_DB_URL` is configured; the API records operator state and no-network cursor resets without pulling vendors, while `scripts/run_vendor_live_sync.py` provides an explicitly enabled one-source pull runner that records outcomes in the same circuit-breaker ledger. Packet assembly records now persist source references, citations, linked packet snapshot ids, and durable audit hashes. Notice checklist records persist compliance outcomes, warnings, posting proof, and durable audit hashes. Browser QA now checks loading, success, empty, error, and partial states plus keyboard, focus, contrast, and console evidence, and release screenshots are bound to the current docs page through shared CivicCore verification helpers. CivicMeetings v1.0.4 now pairs with the published `civiccore` 1.2.1 wheel from the `v1.2.1` release asset. The first staff auth foundation is now explicit: fresh installs default to `CIVICCLERK_STAFF_AUTH_MODE=protected` so anonymous staff writes are denied, local rehearsals can explicitly opt into `CIVICCLERK_STAFF_AUTH_MODE=open`, municipal identity-provider deployments can set `CIVICCLERK_STAFF_AUTH_MODE=oidc` plus issuer, audience, JWKS, role-claim, algorithm, authorization URL, token URL, client, redirect URI, and session-cookie-secret settings, bearer-protected pilots can set `CIVICCLERK_STAFF_AUTH_MODE=bearer` plus `CIVICCLERK_STAFF_AUTH_TOKEN_ROLES`, and trusted reverse-proxy deployments can set `CIVICCLERK_STAFF_AUTH_MODE=trusted_header` plus `CIVICCLERK_STAFF_SSO_PRINCIPAL_HEADER`, `CIVICCLERK_STAFF_SSO_ROLES_HEADER`, `CIVICCLERK_STAFF_SSO_PROVIDER`, and `CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES`. The `/staff/auth-readiness` endpoint now tells operators whether those OIDC token-validation, OIDC browser-login, bearer, or trusted-proxy settings are merely present or actually deployment-ready, and it includes a loopback-only rehearsal recipe so trusted-header testing does not require inventing a custom proxy first. The staff experience at `/staff` now includes a product cockpit plus first workflow screens for agenda intake, packet assembly/export, notice checklist/posting-proof, meeting outcome, minutes draft, public archive, connector import, and vendor sync work. It is intentionally honest: the cockpit gives clerks a day-at-a-glance desk, reads the live agenda intake queue for ready/pending/needs-revision counts, the Agenda Intake, Packet Assembly, Notice Checklist, Meeting Outcomes, Minutes Draft, and Vendor Sync panels render live queue/record rows with escaped user-submitted titles where applicable and actionable empty/unavailable-store rows, the workflow screens can submit their corresponding live API actions, the auth panel now renders concrete protected-session and protected-write probes from `/staff/auth-readiness` when OIDC, bearer, or trusted-header mode is ready, it surfaces the loopback-only local proxy rehearsal command and env vars when trusted-header mode is being staged, and the broader multi-role React clerk console is now beginning under `frontend/`. The React slice uses the CivicSuite mockup direction for a real staff shell, meeting body management, meeting scheduling, meeting calendar, lifecycle ribbon, audit/evidence drawer, pre-lock schedule editing, Agenda Intake submit/review/promotion, Packet Builder promoted-item selection, packet draft creation, per-meeting queue review, packet finalization, Notice Checklist statutory deadline review, legal-blocker copy, posting-proof attachment, immutable audit-hash evidence, Public Posting resident-safe list/detail/search, Meeting Outcomes motion/vote/action capture with immutable-record guidance, Minutes Draft source/citation/provenance capture, Vendor Sync source-health/circuit-breaker/cursor visibility with no-network run logging and full-reconciliation reset guidance, and no-dead-end QA states. The Docker profile now seeds Brookfield demo data so city IT can open the React app and see live work immediately; the unsigned Windows installer wraps that same stack for install/repair and daily start. The resident-facing `/public` route in the nginx product path now opens the React public portal directly, loads public calendar records, public-safe detail, and anonymous archive search from the live public APIs, and keeps restricted-session existence, counts, and summaries out of resident copy. @@ -520,10 +522,10 @@ For deployment hardening, `scripts/check_deployment_readiness.py` now prints a n ### CivicCode live handoff emitter -CivicClerk emits ordinance/resolution handoff records to CivicCode when the +CivicMeetings emits ordinance/resolution handoff records to CivicCode when the city-core installer or operator configures `CIVICCODE_INTAKE_URL` and the suite bearer handoff value. On successful -`POST /meetings/{meeting_id}/ordinance-resolution-handoff`, CivicClerk maps the +`POST /meetings/{meeting_id}/ordinance-resolution-handoff`, CivicMeetings maps the meeting, motion/agenda provenance, affected sections, source document reference, and adopted text into CivicCode's existing `/api/v1/civiccode/staff/civicclerk/ordinance-events` intake contract. The @@ -536,13 +538,13 @@ local handoff record always shows the result: - `EMIT_SKIPPED_UNCONFIGURED` when either required setting is missing. Retry failed or previously unconfigured records with -`POST /meetings/{meeting_id}/ordinance-resolution-handoff/retry`. CivicClerk does +`POST /meetings/{meeting_id}/ordinance-resolution-handoff/retry`. CivicMeetings does not run an infinite background retry loop; operators should fix the URL, shared value, or CivicCode health issue shown in the local record and then retry. For protected deployment smoke checks, `scripts/check_protected_deployment_smoke.py --env-file path\to\deployment.env` now loads the completed env profile, requires strict deployment readiness, verifies `/health` and `/staff/auth-readiness`, executes the readiness-provided protected session probe, executes the protected write probe, and redacts bearer tokens from output. Trusted-header profiles use `127.0.0.1` as the default in-process proxy source; pass `--trusted-proxy-client-ip` when the completed profile allowlists a different proxy test address. The sample profile intentionally fails this smoke until placeholders are replaced. -For local wheel backup/restore rehearsal, `scripts/check_backup_restore_rehearsal.py` creates a timestamped run under `.backup-restore-rehearsal`, seeds the SQLite-backed agenda intake, agenda item, meeting, packet assembly, and notice checklist stores, writes packet export evidence, copies those files into a backup directory with `civicclerk-backup-manifest.json`, restores them to separate `restored-data` and `restored-exports` directories, and reopens the restored records through CivicClerk repositories. Operators can preview the Windows-first wrapper with `powershell -ExecutionPolicy Bypass -File scripts/start_backup_restore_rehearsal.ps1 -PrintOnly` or the Bash wrapper with `bash scripts/start_backup_restore_rehearsal.sh --print-only`; failures name the file or record that did not survive and tell the operator to keep the run directory, fix the backup source or env var, and rerun with a new run id. +For local wheel backup/restore rehearsal, `scripts/check_backup_restore_rehearsal.py` creates a timestamped run under `.backup-restore-rehearsal`, seeds the SQLite-backed agenda intake, agenda item, meeting, packet assembly, and notice checklist stores, writes packet export evidence, copies those files into a backup directory with `civicclerk-backup-manifest.json`, restores them to separate `restored-data` and `restored-exports` directories, and reopens the restored records through CivicMeetings repositories. Operators can preview the Windows-first wrapper with `powershell -ExecutionPolicy Bypass -File scripts/start_backup_restore_rehearsal.ps1 -PrintOnly` or the Bash wrapper with `bash scripts/start_backup_restore_rehearsal.sh --print-only`; failures name the file or record that did not survive and tell the operator to keep the run directory, fix the backup source or env var, and rerun with a new run id. For Docker/PostgreSQL backup/restore rehearsal, `scripts/check_docker_backup_restore_rehearsal.py` works against the running Compose stack instead of the SQLite wheel stores. Operators can preview it with `powershell -ExecutionPolicy Bypass -File scripts/start_docker_backup_restore_rehearsal.ps1 -PrintOnly` or `bash scripts/start_docker_backup_restore_rehearsal.sh --print-only`; rerunning without the print-only flag creates `.docker-backup-restore-rehearsal`, uses `pg_dump` to write `backup/civicclerk-postgres.dump`, creates a temporary restore database, runs `pg_restore`, records restored application tables in `restore-verification.json`, writes `backup/civicclerk-docker-backup-manifest.json`, and drops the temporary restore database by default. It does not drop, clean, or overwrite the source `civicclerk` database. diff --git a/SECURITY.md b/SECURITY.md index 93c7871..4b2282b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,6 @@ # Security Policy -CivicClerk is not installable yet. Security reports should still be +CivicMeetings is not installable yet. Security reports should still be filed privately because meeting workflows will eventually contain privileged and closed-session material. diff --git a/SUPPORT.md b/SUPPORT.md index 274ec1a..e023787 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,6 +1,6 @@ # Support -CivicClerk is currently a scaffold. For now: +CivicMeetings is currently a scaffold. For now: - Use GitHub Issues for bugs in documentation or repo setup. - Use GitHub Discussions for product questions and MVP design discussion. diff --git a/TDD_LOG.md b/TDD_LOG.md index 13c7900..078dcac 100644 --- a/TDD_LOG.md +++ b/TDD_LOG.md @@ -50,7 +50,7 @@ "tests_failing": 15, "files_changed": ["civicclerk/models.py", "TDD_LOG.md"], "commit_sha": "c1eb0a3", - "notes": "Added canonical SQLAlchemy table metadata for all fourteen CivicClerk tables using CivicCore Base." + "notes": "Added canonical SQLAlchemy table metadata for all fourteen CivicMeetings tables using CivicCore Base." }, { "milestone": 2, @@ -60,7 +60,7 @@ "tests_failing": 1, "files_changed": ["civicclerk/migrations/alembic.ini", "civicclerk/migrations/env.py", "civicclerk/migrations/versions/civicclerk_0001_schema.py", "TDD_LOG.md"], "commit_sha": "3386c2d", - "notes": "Added CivicClerk Alembic scaffold and idempotent first migration for the fourteen canonical tables." + "notes": "Added CivicMeetings Alembic scaffold and idempotent first migration for the fourteen canonical tables." }, { "milestone": 2, @@ -330,7 +330,7 @@ "tests_failing": 0, "files_changed": [".github/workflows/release.yml", "CHANGELOG.md", "README.md", "USER-MANUAL.md", "civicclerk/__init__.py", "civicclerk/main.py", "docs/index.html", "docs/screenshots/milestone12-desktop.png", "docs/screenshots/milestone12-mobile.png", "pyproject.toml", "scripts/verify-docs.sh", "scripts/verify-release.sh", "tests/test_milestone_1_runtime_foundation.py", "tests/test_milestone_12_release.py"], "commit_sha": "bd7fbae", - "notes": "Prepared the CivicClerk v0.1.0 release: synchronized version surfaces, added release workflow and verify-release gate, built wheel/sdist with SHA256 checksums, updated current-facing docs and root endpoint, and captured desktop/mobile browser QA evidence." + "notes": "Prepared the CivicMeetings v0.1.0 release: synchronized version surfaces, added release workflow and verify-release gate, built wheel/sdist with SHA256 checksums, updated current-facing docs and root endpoint, and captured desktop/mobile browser QA evidence." }, { "milestone": 12, diff --git a/USER-MANUAL.md b/USER-MANUAL.md index ce7c53c..ab4b277 100644 --- a/USER-MANUAL.md +++ b/USER-MANUAL.md @@ -1,11 +1,11 @@ -# CivicClerk User Manual +# CivicMeetings User Manual -Status: CivicClerk v1.0.4 runtime foundation label is provisional during release recovery +Status: CivicMeetings v1.0.4 runtime foundation label is provisional during release recovery Version: `1.0.4` ## Release Recovery Notice -CivicClerk is not product-ready for public promotion while the CivicSuite +CivicMeetings is not product-ready for public promotion while the CivicSuite release recovery is active. The current `v1.0.4` recovery patch is the supported release until the repo passes the recovery gates: full backend tests, frontend tests, tracked Playwright user-flow tests, WSL runtime install proof, consistency @@ -17,9 +17,9 @@ occurred. ## Part 1: Non-Technical Overview -### What CivicClerk is +### What CivicMeetings is -CivicClerk will help city clerks manage the legal record of public +CivicMeetings will help city clerks manage the legal record of public meetings. It is planned to cover agendas, packets, notices, minutes, votes, motions, ordinances, resolutions, and public meeting archives. @@ -50,7 +50,7 @@ draft language, but staff remain in control. ### Current status -CivicClerk currently contains a runtime foundation, canonical schema +CivicMeetings currently contains a runtime foundation, canonical schema metadata, Alembic migration scaffolding, agenda item lifecycle enforcement, meeting lifecycle enforcement, packet snapshot versioning, notice compliance enforcement, immutable motion capture, immutable vote capture, @@ -64,7 +64,7 @@ minutes drafting, ordinance/resolution extraction, closed-session safe refusal, and public plain-language meeting explanation, local-first connector imports for Granicus, Legistar, PrimeGov, and NovusAGENDA, no-network vendor live-sync readiness plus durable source/run -ledgering, accessibility/browser QA gates, provisional CivicClerk v1.0.4 release +ledgering, accessibility/browser QA gates, provisional CivicMeetings v1.0.4 release artifacts, CivicCore 1.2.1 freeze-backed packet export bundles, a database-backed agenda intake queue with clerk readiness review, database-backed meeting records with lifecycle audit entries, database-backed packet assembly records @@ -138,7 +138,7 @@ check. OIDC mode uses `CIVICCLERK_STAFF_AUTH_MODE=oidc` plus `CIVICCLERK_STAFF_OIDC_REDIRECT_URI`, and `CIVICCLERK_STAFF_OIDC_SESSION_COOKIE_SECRET`; `/staff/login` redirects to the provider with authorization-code + PKCE parameters, `/staff/oidc/callback` -validates the returned token, and CivicClerk stores a signed HttpOnly staff +validates the returned token, and CivicMeetings stores a signed HttpOnly staff session cookie rather than the raw OIDC token. The React dashboard now makes that session state visible in a Staff Access panel. A clerk sees whether the browser is in protected default mode, local open mode, signed in with @@ -166,7 +166,7 @@ The resident-facing `/public` portal now loads public calendar records, public-safe detail, and anonymous archive search from the live public APIs. It also explains empty public-record states and keeps closed-session material out of anonymous resident views. The React staff workspace now exists under -`frontend/`. It translates the CivicSuite mockup into the real CivicClerk +`frontend/`. It translates the CivicSuite mockup into the real CivicMeetings frontend direction: staff shell, meeting calendar, meeting detail lifecycle ribbon, audit/evidence drawer, and loading/success/empty/error/partial states with actionable copy. It now loads the live `/api/meetings` list for @@ -240,7 +240,7 @@ actionable fix guidance before scheduled vendor-network pulls are enabled. ### Deployment model -CivicClerk now has the first CivicSuite-style Docker Compose stack for local +CivicMeetings now has the first CivicSuite-style Docker Compose stack for local product rehearsal: - local Docker-based deployment @@ -275,7 +275,7 @@ under `CIVICCLERK_CONNECTOR_SYNC_LEDGER_PATH`. This scheduled path still reads local files only; it does not contact Granicus, Legistar, PrimeGov, NovusAGENDA, or any vendor network. -By default, Compose sets `CIVICCLERK_DEMO_SEED=1`. On API startup, CivicClerk +By default, Compose sets `CIVICCLERK_DEMO_SEED=1`. On API startup, CivicMeetings creates a Brookfield rehearsal dataset with meeting bodies, meetings in multiple lifecycle states, one promoted agenda intake item, a finalized packet, a posted notice checklist with statutory basis and posting proof, captured motion/vote @@ -299,7 +299,7 @@ Brookfield demo data instead of an empty shell. ### Prompt library and approval ceremony -CivicClerk ships nine versioned YAML prompts in `prompts/`: agenda item +CivicMeetings ships nine versioned YAML prompts in `prompts/`: agenda item summary, staff report normalizer, packet completeness reviewer, notice compliance reviewer, motion/vote summary, minutes drafter, ordinance/resolution extractor, closed-session safe summarizer/refuser, and @@ -524,7 +524,7 @@ These endpoints validate and record source/run/failure state only. They return contact Granicus, Legistar, PrimeGov, NovusAGENDA, or any other vendor network. The cursor reset path clears or moves `last_success_cursor_at` locally so the next controlled pull can perform a full reconciliation or replay from an -operator-selected point. CivicClerk saves the operator reason as a +operator-selected point. CivicMeetings saves the operator reason as a `cursor_reset` run-log event and returns that `reset_event` in the API response; the reset itself never calls the vendor. @@ -541,7 +541,7 @@ HTTP request, reads credentials from the named env var instead of the URL, normalizes returned JSON through the existing connector contract, writes an optional report without secrets, and records success or failure in the same circuit-breaker ledger. The report includes `delta_request_url`, -`cursor_param`, `cursor_value`, and `cursor_advanced_at`. CivicClerk advances +`cursor_param`, `cursor_value`, and `cursor_advanced_at`. CivicMeetings advances the persisted `last_success_cursor_at` only after every discovered payload normalizes successfully; failed and partial runs leave the cursor unchanged so the next pull can retry without skipping records. @@ -658,7 +658,7 @@ without the print-only flag to execute the rehearsal under agenda intake, agenda item, meeting, packet assembly, and notice checklist records, copies the databases and export evidence into a backup directory, restores them to separate `restored-data` and `restored-exports` directories, -then reopens the restored records through CivicClerk repositories. If a check +then reopens the restored records through CivicMeetings repositories. If a check fails, keep the run directory, inspect the named file or record, fix the backup source or environment variable, and rerun with a new run id. @@ -682,7 +682,7 @@ print-only flag. The helper creates `.docker-backup-restore-rehearsal`, runs `pg_restore`, verifies restored application tables, writes `backup/civicclerk-docker-backup-manifest.json`, and drops the temporary restore database unless `--keep-restore-database` is supplied. It does not drop, clean, -or overwrite the source CivicClerk database. +or overwrite the source CivicMeetings database. If staff access will stay local for a demo or rehearsal, keep `CIVICCLERK_STAFF_AUTH_MODE=protected`. If a local rehearsal must stay open, explicitly opt into `CIVICCLERK_STAFF_AUTH_MODE=open`; otherwise move to `oidc`, `bearer`, or `trusted_header` before user testing and use @@ -697,7 +697,7 @@ If trusted-header testing is happening on one loopback workstation before a real reverse proxy is available, use the returned `local_proxy_rehearsal` contract, set `CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES=127.0.0.1/32`, run `python scripts/local_trusted_header_proxy.py`, and send the browser through -that helper so CivicClerk only trusts loopback proxy traffic during rehearsal. +that helper so CivicMeetings only trusts loopback proxy traffic during rehearsal. If the deployment is moving to a real reverse proxy, use the returned `reverse_proxy_reference` block and start from `docs/examples/trusted-header-nginx.conf` before replacing the placeholder TLS @@ -761,11 +761,11 @@ provenance and actionable errors, without requiring outbound runtime calls. Milestone 11 adds browser QA evidence and a CI gate for loading, success, empty, error, and partial states plus keyboard navigation, focus states, contrast, and console checks. Milestone 12 synchronizes version surfaces, -builds release artifacts and checksums, and publishes CivicClerk v1.0.4. +builds release artifacts and checksums, and publishes CivicMeetings v1.0.4. CC-7 extends browser QA to every named spec page through `node scripts/capture-cc7-browser-qa.mjs`; the verification script requires the resulting 200-case ledger before browser-visible changes can merge. -The current production-depth branch pairs CivicClerk with the published `civiccore` 1.2.1 wheel from the `v1.2.1` release asset +The current production-depth branch pairs CivicMeetings with the published `civiccore` 1.2.1 wheel from the `v1.2.1` release asset so packet exports, packet assembly records, notice checklist records, and the browser QA release-evidence gate can use shared CivicCore manifests, provenance, checksums, audit primitives, and verification helpers. @@ -774,7 +774,7 @@ provenance, checksums, audit primitives, and verification helpers. ### Planned module boundaries -CivicClerk owns meeting workflows. It should not become: +CivicMeetings owns meeting workflows. It should not become: - electronic voting software - livestream hosting @@ -784,7 +784,7 @@ CivicClerk owns meeting workflows. It should not become: ### Initial data model sketch Milestone 2 defines the canonical schema and Alembic migration foundation -for these CivicClerk tables. Milestone 3 adds agenda lifecycle enforcement +for these CivicMeetings tables. Milestone 3 adds agenda lifecycle enforcement for agenda items. Milestone 4 adds meeting lifecycle enforcement. Milestone 5 adds packet snapshot versioning and notice compliance enforcement. Milestone 6 adds immutable motion capture, immutable vote capture, and diff --git a/USER-MANUAL.txt b/USER-MANUAL.txt index ce7c53c..ab4b277 100644 --- a/USER-MANUAL.txt +++ b/USER-MANUAL.txt @@ -1,11 +1,11 @@ -# CivicClerk User Manual +# CivicMeetings User Manual -Status: CivicClerk v1.0.4 runtime foundation label is provisional during release recovery +Status: CivicMeetings v1.0.4 runtime foundation label is provisional during release recovery Version: `1.0.4` ## Release Recovery Notice -CivicClerk is not product-ready for public promotion while the CivicSuite +CivicMeetings is not product-ready for public promotion while the CivicSuite release recovery is active. The current `v1.0.4` recovery patch is the supported release until the repo passes the recovery gates: full backend tests, frontend tests, tracked Playwright user-flow tests, WSL runtime install proof, consistency @@ -17,9 +17,9 @@ occurred. ## Part 1: Non-Technical Overview -### What CivicClerk is +### What CivicMeetings is -CivicClerk will help city clerks manage the legal record of public +CivicMeetings will help city clerks manage the legal record of public meetings. It is planned to cover agendas, packets, notices, minutes, votes, motions, ordinances, resolutions, and public meeting archives. @@ -50,7 +50,7 @@ draft language, but staff remain in control. ### Current status -CivicClerk currently contains a runtime foundation, canonical schema +CivicMeetings currently contains a runtime foundation, canonical schema metadata, Alembic migration scaffolding, agenda item lifecycle enforcement, meeting lifecycle enforcement, packet snapshot versioning, notice compliance enforcement, immutable motion capture, immutable vote capture, @@ -64,7 +64,7 @@ minutes drafting, ordinance/resolution extraction, closed-session safe refusal, and public plain-language meeting explanation, local-first connector imports for Granicus, Legistar, PrimeGov, and NovusAGENDA, no-network vendor live-sync readiness plus durable source/run -ledgering, accessibility/browser QA gates, provisional CivicClerk v1.0.4 release +ledgering, accessibility/browser QA gates, provisional CivicMeetings v1.0.4 release artifacts, CivicCore 1.2.1 freeze-backed packet export bundles, a database-backed agenda intake queue with clerk readiness review, database-backed meeting records with lifecycle audit entries, database-backed packet assembly records @@ -138,7 +138,7 @@ check. OIDC mode uses `CIVICCLERK_STAFF_AUTH_MODE=oidc` plus `CIVICCLERK_STAFF_OIDC_REDIRECT_URI`, and `CIVICCLERK_STAFF_OIDC_SESSION_COOKIE_SECRET`; `/staff/login` redirects to the provider with authorization-code + PKCE parameters, `/staff/oidc/callback` -validates the returned token, and CivicClerk stores a signed HttpOnly staff +validates the returned token, and CivicMeetings stores a signed HttpOnly staff session cookie rather than the raw OIDC token. The React dashboard now makes that session state visible in a Staff Access panel. A clerk sees whether the browser is in protected default mode, local open mode, signed in with @@ -166,7 +166,7 @@ The resident-facing `/public` portal now loads public calendar records, public-safe detail, and anonymous archive search from the live public APIs. It also explains empty public-record states and keeps closed-session material out of anonymous resident views. The React staff workspace now exists under -`frontend/`. It translates the CivicSuite mockup into the real CivicClerk +`frontend/`. It translates the CivicSuite mockup into the real CivicMeetings frontend direction: staff shell, meeting calendar, meeting detail lifecycle ribbon, audit/evidence drawer, and loading/success/empty/error/partial states with actionable copy. It now loads the live `/api/meetings` list for @@ -240,7 +240,7 @@ actionable fix guidance before scheduled vendor-network pulls are enabled. ### Deployment model -CivicClerk now has the first CivicSuite-style Docker Compose stack for local +CivicMeetings now has the first CivicSuite-style Docker Compose stack for local product rehearsal: - local Docker-based deployment @@ -275,7 +275,7 @@ under `CIVICCLERK_CONNECTOR_SYNC_LEDGER_PATH`. This scheduled path still reads local files only; it does not contact Granicus, Legistar, PrimeGov, NovusAGENDA, or any vendor network. -By default, Compose sets `CIVICCLERK_DEMO_SEED=1`. On API startup, CivicClerk +By default, Compose sets `CIVICCLERK_DEMO_SEED=1`. On API startup, CivicMeetings creates a Brookfield rehearsal dataset with meeting bodies, meetings in multiple lifecycle states, one promoted agenda intake item, a finalized packet, a posted notice checklist with statutory basis and posting proof, captured motion/vote @@ -299,7 +299,7 @@ Brookfield demo data instead of an empty shell. ### Prompt library and approval ceremony -CivicClerk ships nine versioned YAML prompts in `prompts/`: agenda item +CivicMeetings ships nine versioned YAML prompts in `prompts/`: agenda item summary, staff report normalizer, packet completeness reviewer, notice compliance reviewer, motion/vote summary, minutes drafter, ordinance/resolution extractor, closed-session safe summarizer/refuser, and @@ -524,7 +524,7 @@ These endpoints validate and record source/run/failure state only. They return contact Granicus, Legistar, PrimeGov, NovusAGENDA, or any other vendor network. The cursor reset path clears or moves `last_success_cursor_at` locally so the next controlled pull can perform a full reconciliation or replay from an -operator-selected point. CivicClerk saves the operator reason as a +operator-selected point. CivicMeetings saves the operator reason as a `cursor_reset` run-log event and returns that `reset_event` in the API response; the reset itself never calls the vendor. @@ -541,7 +541,7 @@ HTTP request, reads credentials from the named env var instead of the URL, normalizes returned JSON through the existing connector contract, writes an optional report without secrets, and records success or failure in the same circuit-breaker ledger. The report includes `delta_request_url`, -`cursor_param`, `cursor_value`, and `cursor_advanced_at`. CivicClerk advances +`cursor_param`, `cursor_value`, and `cursor_advanced_at`. CivicMeetings advances the persisted `last_success_cursor_at` only after every discovered payload normalizes successfully; failed and partial runs leave the cursor unchanged so the next pull can retry without skipping records. @@ -658,7 +658,7 @@ without the print-only flag to execute the rehearsal under agenda intake, agenda item, meeting, packet assembly, and notice checklist records, copies the databases and export evidence into a backup directory, restores them to separate `restored-data` and `restored-exports` directories, -then reopens the restored records through CivicClerk repositories. If a check +then reopens the restored records through CivicMeetings repositories. If a check fails, keep the run directory, inspect the named file or record, fix the backup source or environment variable, and rerun with a new run id. @@ -682,7 +682,7 @@ print-only flag. The helper creates `.docker-backup-restore-rehearsal`, runs `pg_restore`, verifies restored application tables, writes `backup/civicclerk-docker-backup-manifest.json`, and drops the temporary restore database unless `--keep-restore-database` is supplied. It does not drop, clean, -or overwrite the source CivicClerk database. +or overwrite the source CivicMeetings database. If staff access will stay local for a demo or rehearsal, keep `CIVICCLERK_STAFF_AUTH_MODE=protected`. If a local rehearsal must stay open, explicitly opt into `CIVICCLERK_STAFF_AUTH_MODE=open`; otherwise move to `oidc`, `bearer`, or `trusted_header` before user testing and use @@ -697,7 +697,7 @@ If trusted-header testing is happening on one loopback workstation before a real reverse proxy is available, use the returned `local_proxy_rehearsal` contract, set `CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES=127.0.0.1/32`, run `python scripts/local_trusted_header_proxy.py`, and send the browser through -that helper so CivicClerk only trusts loopback proxy traffic during rehearsal. +that helper so CivicMeetings only trusts loopback proxy traffic during rehearsal. If the deployment is moving to a real reverse proxy, use the returned `reverse_proxy_reference` block and start from `docs/examples/trusted-header-nginx.conf` before replacing the placeholder TLS @@ -761,11 +761,11 @@ provenance and actionable errors, without requiring outbound runtime calls. Milestone 11 adds browser QA evidence and a CI gate for loading, success, empty, error, and partial states plus keyboard navigation, focus states, contrast, and console checks. Milestone 12 synchronizes version surfaces, -builds release artifacts and checksums, and publishes CivicClerk v1.0.4. +builds release artifacts and checksums, and publishes CivicMeetings v1.0.4. CC-7 extends browser QA to every named spec page through `node scripts/capture-cc7-browser-qa.mjs`; the verification script requires the resulting 200-case ledger before browser-visible changes can merge. -The current production-depth branch pairs CivicClerk with the published `civiccore` 1.2.1 wheel from the `v1.2.1` release asset +The current production-depth branch pairs CivicMeetings with the published `civiccore` 1.2.1 wheel from the `v1.2.1` release asset so packet exports, packet assembly records, notice checklist records, and the browser QA release-evidence gate can use shared CivicCore manifests, provenance, checksums, audit primitives, and verification helpers. @@ -774,7 +774,7 @@ provenance, checksums, audit primitives, and verification helpers. ### Planned module boundaries -CivicClerk owns meeting workflows. It should not become: +CivicMeetings owns meeting workflows. It should not become: - electronic voting software - livestream hosting @@ -784,7 +784,7 @@ CivicClerk owns meeting workflows. It should not become: ### Initial data model sketch Milestone 2 defines the canonical schema and Alembic migration foundation -for these CivicClerk tables. Milestone 3 adds agenda lifecycle enforcement +for these CivicMeetings tables. Milestone 3 adds agenda lifecycle enforcement for agenda items. Milestone 4 adds meeting lifecycle enforcement. Milestone 5 adds packet snapshot versioning and notice compliance enforcement. Milestone 6 adds immutable motion capture, immutable vote capture, and diff --git a/civicclerk/__init__.py b/civicclerk/__init__.py index 753d30f..6d04d18 100644 --- a/civicclerk/__init__.py +++ b/civicclerk/__init__.py @@ -1,3 +1,3 @@ -"""CivicClerk runtime package.""" +"""CivicMeetings runtime package.""" __version__ = "1.0.4" diff --git a/civicclerk/agenda_lifecycle.py b/civicclerk/agenda_lifecycle.py index d6c427c..7ea7d91 100644 --- a/civicclerk/agenda_lifecycle.py +++ b/civicclerk/agenda_lifecycle.py @@ -1,4 +1,4 @@ -"""Agenda item lifecycle enforcement for CivicClerk.""" +"""Agenda item lifecycle enforcement for CivicMeetings.""" from __future__ import annotations diff --git a/civicclerk/connectors.py b/civicclerk/connectors.py index d6ca007..45f54f4 100644 --- a/civicclerk/connectors.py +++ b/civicclerk/connectors.py @@ -1,4 +1,4 @@ -"""CivicClerk re-exports shared local-first connector import helpers.""" +"""CivicMeetings re-exports shared local-first connector import helpers.""" from civiccore.connectors import ( ConnectorImportError, diff --git a/civicclerk/demo_seed.py b/civicclerk/demo_seed.py index e80fe31..807b657 100644 --- a/civicclerk/demo_seed.py +++ b/civicclerk/demo_seed.py @@ -1,4 +1,4 @@ -"""Seed a believable local CivicClerk demo for Docker-based product rehearsal.""" +"""Seed a believable local CivicMeetings demo for Docker-based product rehearsal.""" from __future__ import annotations diff --git a/civicclerk/integration_contracts.py b/civicclerk/integration_contracts.py index b4d038e..bac0317 100644 --- a/civicclerk/integration_contracts.py +++ b/civicclerk/integration_contracts.py @@ -87,7 +87,7 @@ def integration_contracts() -> list[IntegrationContract]: "unavailable-service fallback", ), absent_dependency_behavior=( - "CivicClerk keeps local public archive search authoritative and returns an " + "CivicMeetings keeps local public archive search authoritative and returns an " "actionable unavailable-state contract instead of implying CivicRecords is live." ), operator_fix=( @@ -116,7 +116,7 @@ def integration_contracts() -> list[IntegrationContract]: "retry/audit ledger shape", ), absent_dependency_behavior=( - "CivicClerk stores the handoff locally as READY_FOR_CODE_OR_LEGAL_REVIEW and " + "CivicMeetings stores the handoff locally as READY_FOR_CODE_OR_LEGAL_REVIEW and " "keeps a file-export path available until CivicCode is reachable." ), operator_fix=( @@ -145,7 +145,7 @@ def integration_contracts() -> list[IntegrationContract]: "human codifier review gate", ), absent_dependency_behavior=( - "If CivicCode or a codifier API is absent, CivicClerk produces a checksumed " + "If CivicCode or a codifier API is absent, CivicMeetings produces a checksumed " "handoff packet for the clerk/legal/codifier workflow without auto-codifying." ), operator_fix=( @@ -174,7 +174,7 @@ def integration_contracts() -> list[IntegrationContract]: "CMS unavailable fallback", ), absent_dependency_behavior=( - "CivicClerk continues to serve its resident portal and produces a CMS-ready " + "CivicMeetings continues to serve its resident portal and produces a CMS-ready " "posting preview until a city-specific CMS adapter is configured." ), operator_fix=( @@ -204,7 +204,7 @@ def integration_contracts() -> list[IntegrationContract]: "circuit breaker and cursor controls", ), absent_dependency_behavior=( - "CivicClerk records source configuration, health, cursor resets, and run outcomes " + "CivicMeetings records source configuration, health, cursor resets, and run outcomes " "without pulling vendor networks until a controlled adapter run is explicitly enabled." ), operator_fix=( @@ -262,7 +262,7 @@ def integration_readiness_payload() -> dict[str, object]: "contracts": [contract.public_dict() for contract in contracts], "checks": [check.public_dict() for check in checks], "message": ( - "CivicClerk integration depth is framed as live-wire or in-process boundary validation; " + "CivicMeetings integration depth is framed as live-wire or in-process boundary validation; " "mock adversarial checks remain regression coverage, not release-depth proof." ), "fix": ( @@ -288,14 +288,14 @@ def _check_civicrecords_unavailable_fallback() -> IntegrationCheck: fallback = { "status": "degraded", "local_archive_available": True, - "fix": "Continue with CivicClerk local archive search, then retry CivicRecords after IT restores the service.", + "fix": "Continue with CivicMeetings local archive search, then retry CivicRecords after IT restores the service.", } ok = fallback["local_archive_available"] and "retry CivicRecords" in fallback["fix"] return IntegrationCheck( contract_id="civicrecords-search", scenario="dependency_unavailable_fallback", ok=ok, - message="CivicRecords unavailable mock keeps CivicClerk local archive search available with fix guidance.", + message="CivicRecords unavailable mock keeps CivicMeetings local archive search available with fix guidance.", fix=str(fallback["fix"]), ) diff --git a/civicclerk/main.py b/civicclerk/main.py index d40e5d7..add513a 100644 --- a/civicclerk/main.py +++ b/civicclerk/main.py @@ -1,4 +1,4 @@ -"""FastAPI runtime foundation for CivicClerk.""" +"""FastAPI runtime foundation for CivicMeetings.""" from __future__ import annotations @@ -84,9 +84,9 @@ from civiccore import __version__ as CIVICCORE_VERSION app = FastAPI( - title="CivicClerk", + title="CivicMeetings", version=__version__, - summary="Runtime foundation for CivicClerk municipal meeting workflows.", + summary="Runtime foundation for CivicMeetings municipal meeting workflows.", ) agenda_items = AgendaItemStore() @@ -492,17 +492,17 @@ class VendorSyncCursorReset(BaseModel): async def root() -> dict[str, str]: """Describe what the runtime foundation currently provides.""" return { - "name": "CivicClerk", + "name": "CivicMeetings", "status": f"v{__version__} runtime foundation release", "message": ( - "CivicClerk agenda item, meeting lifecycle, packet snapshot, and notice compliance " + "CivicMeetings agenda item, meeting lifecycle, packet snapshot, and notice compliance " "enforcement are online with immutable motion, vote, action-item, and citation-gated " "minutes draft capture plus permission-aware public calendar and archive endpoints; " "prompt YAML and offline evaluation gates protect policy-bearing prompt changes; " "local-first Granicus, Legistar, PrimeGov, and NovusAGENDA imports now normalize " f"source provenance; CivicCore v{CIVICCORE_VERSION} packet export bundles now include manifests, " "checksums, provenance, and hash-chained audit evidence; " - "CivicClerk notice checks now reuse the shared CivicCore notice compliance helper while preserving " + "CivicMeetings notice checks now reuse the shared CivicCore notice compliance helper while preserving " "meeting-specific warning and posting flows; " "accessibility and browser QA " "gates now verify loading, success, empty, error, partial, keyboard, focus, contrast, " @@ -531,7 +531,7 @@ async def root() -> dict[str, str]: "meeting records can now persist through the configured meeting database; " "meeting schedule fields now include body linkage and location, with pre-lock edits " "audited before meetings move in progress; " - f"CivicClerk is versioned as v{__version__} with the production-depth service slices included; " + f"CivicMeetings is versioned as v{__version__} with the production-depth service slices included; " "staff workflow APIs now support a local-open rehearsal mode, a bearer-protected bridge mode, " "and a trusted-header reverse-proxy mode with a required trusted-proxy CIDR allowlist, " "with the /staff screen showing the current access " @@ -685,7 +685,7 @@ async def staff_session(request: Request) -> dict[str, object]: return response response["message"] = "OIDC staff identity accepted from the configured municipal provider." response["fix"] = ( - "Keep the identity provider app roles or groups mapped to CivicClerk staff roles." + "Keep the identity provider app roles or groups mapped to CivicMeetings staff roles." ) return response @@ -694,7 +694,7 @@ async def staff_session(request: Request) -> dict[str, object]: response["fix"] = ( f"Keep {trusted_header_config.provider_name} stripping client-supplied copies of " f"{trusted_header_config.principal_header_name} and {trusted_header_config.roles_header_name} " - "before CivicClerk." + "before CivicMeetings." ) response["principal_header"] = trusted_header_config.principal_header_name response["roles_header"] = trusted_header_config.roles_header_name @@ -788,7 +788,7 @@ async def staff_oidc_callback(request: Request) -> RedirectResponse: status_code=400, detail={ "message": "OIDC sign-in state did not match.", - "fix": "Restart sign-in from /staff/login. If this repeats, confirm cookies are allowed for the CivicClerk host.", + "fix": "Restart sign-in from /staff/login. If this repeats, confirm cookies are allowed for the CivicMeetings host.", }, ) code_verifier = request.cookies.get(STAFF_OIDC_PKCE_COOKIE_NAME) @@ -797,7 +797,7 @@ async def staff_oidc_callback(request: Request) -> RedirectResponse: status_code=400, detail={ "message": "OIDC sign-in PKCE verifier is missing.", - "fix": "Restart sign-in from /staff/login. If this repeats, confirm cookies are allowed for the CivicClerk host.", + "fix": "Restart sign-in from /staff/login. If this repeats, confirm cookies are allowed for the CivicMeetings host.", }, ) code = request.query_params.get("code") @@ -828,7 +828,7 @@ async def staff_oidc_callback(request: Request) -> RedirectResponse: status_code=502, detail={ "message": "OIDC token response did not include an ID token or access token.", - "fix": "Confirm the provider app registration issues an ID token or API access token for CivicClerk.", + "fix": "Confirm the provider app registration issues an ID token or API access token for CivicMeetings.", }, ) principal = authorize_oidc_staff_token( @@ -859,7 +859,7 @@ async def staff_oidc_callback(request: Request) -> RedirectResponse: @app.get("/staff/logout") @app.post("/staff/logout") async def staff_logout(request: Request) -> RedirectResponse: - """Clear the local CivicClerk staff browser session.""" + """Clear the local CivicMeetings staff browser session.""" _revoke_suite_session_from_request(request) response = RedirectResponse("/staff", status_code=302) @@ -1937,7 +1937,7 @@ async def _emit_civiccode_handoff(record: dict[str, object]) -> None: def _minutes_ai_unavailable_detail(reason: str) -> dict[str, str]: return { - "message": "AI assist unavailable; CivicClerk core workflow is still available.", + "message": "AI assist unavailable; CivicMeetings core workflow is still available.", "fix": ( f"Start Ollama, confirm {CIVICCLERK_OLLAMA_BASE_URL_ENV_VAR}, and retry the minutes-AI assist. " "Manual cited minutes drafting remains available through /meetings/{meeting_id}/minutes/drafts." @@ -2389,7 +2389,7 @@ async def list_vendor_live_sync_sources() -> dict[str, object]: return { "network_calls": False, "sources": sources, - "message": "Vendor live-sync source health is loaded from CivicClerk persistence.", + "message": "Vendor live-sync source health is loaded from CivicMeetings persistence.", "fix": "If a source is degraded or circuit_open, review its run log before enabling scheduled pulls.", } @@ -2476,7 +2476,7 @@ async def list_vendor_live_sync_runs(source_id: str) -> dict[str, object]: "network_calls": False, "source": source.public_dict(), "runs": runs, - "message": "Run history is loaded from CivicClerk persistence; no vendor network call was attempted.", + "message": "Run history is loaded from CivicMeetings persistence; no vendor network call was attempted.", } @@ -2600,7 +2600,7 @@ def _resolve_archive_search_principal( ) -> AuthenticatedPrincipal | None: return resolve_optional_bearer_roles( credentials, - service_name="CivicClerk", + service_name="CivicMeetings", feature_name="archive search staff access", token_roles_env_var="CIVICCLERK_AUTH_TOKEN_ROLES", allowed_roles={"archive_reader", "clerk_admin", "city_attorney"}, @@ -2636,7 +2636,7 @@ def _authorize_staff_principal(request: Request) -> AuthenticatedPrincipal: return suite_principal return authorize_bearer_roles( credentials, - service_name="CivicClerk", + service_name="CivicMeetings", feature_name="staff workflow access", token_roles_env_var=STAFF_AUTH_TOKEN_ROLES_ENV_VAR, allowed_roles=STAFF_ALLOWED_ROLES, @@ -2645,14 +2645,14 @@ def _authorize_staff_principal(request: Request) -> AuthenticatedPrincipal: trusted_header_config = _get_staff_trusted_header_config() enforce_trusted_proxy_source( request.client.host if request.client is not None else None, - service_name="CivicClerk", + service_name="CivicMeetings", feature_name="staff workflow access", config=trusted_header_config, trusted_proxy_env_var=STAFF_AUTH_SSO_TRUSTED_PROXIES_ENV_VAR, ) return authorize_trusted_header_roles( request.headers, - service_name="CivicClerk", + service_name="CivicMeetings", feature_name="staff workflow access", principal_header_name=trusted_header_config.principal_header_name, roles_header_name=trusted_header_config.roles_header_name, @@ -2745,7 +2745,7 @@ def _get_staff_auth_mode() -> str: raise HTTPException( status_code=503, detail={ - "message": "CivicClerk staff auth mode is invalid.", + "message": "CivicMeetings staff auth mode is invalid.", "fix": ( f"Set {STAFF_AUTH_MODE_ENV_VAR} to '{STAFF_PROTECTED_MODE}' to deny anonymous writes, " f"'{STAFF_OPEN_MODE}' for local rehearsal, " @@ -2819,13 +2819,13 @@ def _get_local_trusted_header_proxy_rehearsal( roles_header_name: LOCAL_TRUSTED_HEADER_PROXY_DEFAULT_ROLES, }, "steps": [ - "Start CivicClerk on loopback with the app_env values shown here.", + "Start CivicMeetings on loopback with the app_env values shown here.", "Run the helper command on the same workstation to inject placeholder trusted headers.", "Browse or call the helper listen_url instead of the upstream URL so the backend only trusts loopback proxy traffic.", ], "warnings": [ "This helper is for localhost rehearsal only and does not terminate TLS or manage an identity provider.", - "The helper strips client-supplied trusted identity headers before forwarding to CivicClerk.", + "The helper strips client-supplied trusted identity headers before forwarding to CivicMeetings.", ], } @@ -3031,7 +3031,7 @@ def _get_staff_oidc_auth_readiness() -> dict[str, object]: "checks": checks, "message": "OIDC staff auth is configured for municipal identity-provider access tokens.", "fix": ( - "Use /staff/login for browser sign-in, or use an access token with a CivicClerk staff " + "Use /staff/login for browser sign-in, or use an access token with a CivicMeetings staff " "app role or group claim for API smoke checks." if not browser_missing else "Token validation is configured; finish the browser_login settings before clerk browser testing." @@ -3072,9 +3072,9 @@ def _get_staff_trusted_header_readiness() -> dict[str, object]: trusted_header_config.roles_header_name: "", }, "steps": [ - "Authenticate the operator before CivicClerk and map the trusted staff principal plus roles into proxy-controlled headers.", + "Authenticate the operator before CivicMeetings and map the trusted staff principal plus roles into proxy-controlled headers.", "Strip any client-supplied copies of the trusted staff headers before setting the proxy-owned values shown here.", - f"Set {STAFF_AUTH_SSO_TRUSTED_PROXIES_ENV_VAR} to the proxy CIDRs that are allowed to forward those headers to CivicClerk.", + f"Set {STAFF_AUTH_SSO_TRUSTED_PROXIES_ENV_VAR} to the proxy CIDRs that are allowed to forward those headers to CivicMeetings.", ], "warnings": [ "This reference config is a starting point; replace the placeholder TLS paths and authenticated identity variables with your real deployment values.", @@ -3223,7 +3223,7 @@ def _oidc_browser_login_fix(missing: list[str]) -> str: readable = ", ".join(env_names[name] for name in missing if name in env_names) return ( f"Set {readable} before clerk browser sign-in. The redirect URI must point to " - "/staff/oidc/callback on the same CivicClerk host." + "/staff/oidc/callback on the same CivicMeetings host." ) diff --git a/civicclerk/meeting_lifecycle.py b/civicclerk/meeting_lifecycle.py index e919f57..8f1645e 100644 --- a/civicclerk/meeting_lifecycle.py +++ b/civicclerk/meeting_lifecycle.py @@ -1,4 +1,4 @@ -"""Meeting lifecycle enforcement for CivicClerk. +"""Meeting lifecycle enforcement for CivicMeetings. Milestone 4 establishes the meeting state machine and audit contract. Packet assembly, notice compliance, minutes drafting, and archival workflow remain diff --git a/civicclerk/migrations/__init__.py b/civicclerk/migrations/__init__.py index a1c07e9..e14f250 100644 --- a/civicclerk/migrations/__init__.py +++ b/civicclerk/migrations/__init__.py @@ -1 +1 @@ -"""CivicClerk Alembic migration package.""" +"""CivicMeetings Alembic migration package.""" diff --git a/civicclerk/migrations/alembic.ini b/civicclerk/migrations/alembic.ini index fbe6f3a..001a9e7 100644 --- a/civicclerk/migrations/alembic.ini +++ b/civicclerk/migrations/alembic.ini @@ -4,7 +4,7 @@ prepend_sys_path = . version_path_separator = os path_separator = os # Set DATABASE_URL in the environment, or inject sqlalchemy.url on the -# Alembic Config. CivicCore and CivicClerk migrations use that same URL. +# Alembic Config. CivicCore and CivicMeetings migrations use that same URL. [loggers] keys = root,sqlalchemy,alembic diff --git a/civicclerk/migrations/env.py b/civicclerk/migrations/env.py index 4e48b51..61048bd 100644 --- a/civicclerk/migrations/env.py +++ b/civicclerk/migrations/env.py @@ -20,11 +20,11 @@ def _database_url() -> str: - """Resolve the one database URL used by both CivicCore and CivicClerk.""" + """Resolve the one database URL used by both CivicCore and CivicMeetings.""" url = config.get_main_option("sqlalchemy.url") or os.environ.get("DATABASE_URL") if not url: raise RuntimeError( - "CivicClerk migrations require a database URL. Set DATABASE_URL or " + "CivicMeetings migrations require a database URL. Set DATABASE_URL or " "set sqlalchemy.url on the Alembic Config before running upgrade." ) return url diff --git a/civicclerk/migrations/guards.py b/civicclerk/migrations/guards.py index e416127..a4edc84 100644 --- a/civicclerk/migrations/guards.py +++ b/civicclerk/migrations/guards.py @@ -1,4 +1,4 @@ -"""CivicClerk-specific Alembic guards.""" +"""CivicMeetings-specific Alembic guards.""" from __future__ import annotations diff --git a/civicclerk/migrations/versions/__init__.py b/civicclerk/migrations/versions/__init__.py index 529b215..f7971ec 100644 --- a/civicclerk/migrations/versions/__init__.py +++ b/civicclerk/migrations/versions/__init__.py @@ -1 +1 @@ -"""CivicClerk Alembic migration versions.""" +"""CivicMeetings Alembic migration versions.""" diff --git a/civicclerk/migrations/versions/civicclerk_0001_schema.py b/civicclerk/migrations/versions/civicclerk_0001_schema.py index 4d6c53f..0d8dad9 100644 --- a/civicclerk/migrations/versions/civicclerk_0001_schema.py +++ b/civicclerk/migrations/versions/civicclerk_0001_schema.py @@ -1,4 +1,4 @@ -"""Create CivicClerk canonical schema.""" +"""Create CivicMeetings canonical schema.""" from __future__ import annotations diff --git a/civicclerk/migrations/versions/civicclerk_0011_data_model_completion.py b/civicclerk/migrations/versions/civicclerk_0011_data_model_completion.py index 34bc46e..3971704 100644 --- a/civicclerk/migrations/versions/civicclerk_0011_data_model_completion.py +++ b/civicclerk/migrations/versions/civicclerk_0011_data_model_completion.py @@ -1,4 +1,4 @@ -"""Complete CivicClerk canonical data model contracts.""" +"""Complete CivicMeetings canonical data model contracts.""" from __future__ import annotations diff --git a/civicclerk/minutes.py b/civicclerk/minutes.py index db1caa3..8fde66b 100644 --- a/civicclerk/minutes.py +++ b/civicclerk/minutes.py @@ -303,7 +303,7 @@ def _validate_create_inputs( if not is_known_prompt_version(prompt_version): expected = expected_prompt_version_hint() return MinutesValidationError( - message="Minutes drafts must use a prompt version from the CivicClerk YAML prompt library.", + message="Minutes drafts must use a prompt version from the CivicMeetings YAML prompt library.", fix=f"Use prompt_version '{expected}' or another version returned by the prompt library.", ) return validate_minutes_draft( diff --git a/civicclerk/mock_city_environment.py b/civicclerk/mock_city_environment.py index ae95d45..4623a69 100644 --- a/civicclerk/mock_city_environment.py +++ b/civicclerk/mock_city_environment.py @@ -1,4 +1,4 @@ -"""CivicClerk adapters for the shared CivicCore mock city contracts.""" +"""CivicMeetings adapters for the shared CivicCore mock city contracts.""" from __future__ import annotations @@ -90,7 +90,7 @@ def public_dict(self) -> dict[str, Any]: def mock_city_idp_contract() -> MockCityIdpContract: - """Return CivicClerk's module-specific view of the shared mock IdP contract.""" + """Return CivicMeetings' module-specific view of the shared mock IdP contract.""" return MockCityIdpContract( provider="Brookfield Entra ID", @@ -108,7 +108,7 @@ def mock_city_idp_contract() -> MockCityIdpContract: staff_email="clerk@brookfield.example.gov", staff_roles=("clerk_admin", "meeting_editor"), notes=( - "Models the authorization-code + PKCE and JWKS/token contract CivicClerk " + "Models the authorization-code + PKCE and JWKS/token contract CivicMeetings " "must satisfy before replacing mock evidence with a real municipal tenant." ), ) @@ -133,7 +133,7 @@ def mock_city_idp_hostile_fixtures() -> list[MockCityHostileFixture]: target="Brookfield Okta", trigger="staff role is supplied through groups instead of roles", expected_behavior="accept the token when the configured group claim maps to a staff role", - fix="Map the Okta group claim to an allowed CivicClerk staff role before deployment.", + fix="Map the Okta group claim to an allowed CivicMeetings staff role before deployment.", sample={"provider_family": "okta", "claim": "groups", "expected_status": 200}, ), MockCityHostileFixture( @@ -151,16 +151,16 @@ def mock_city_idp_hostile_fixtures() -> list[MockCityHostileFixture]: target="Brookfield Entra ID", trigger="authorization response requires MFA interaction", expected_behavior="preserve the interaction_required result and send the clerk back through sign-in", - fix="Complete the MFA challenge in the municipal identity provider, then return to CivicClerk.", + fix="Complete the MFA challenge in the municipal identity provider, then return to CivicMeetings.", sample={"provider_family": "entra", "oauth_error": "interaction_required", "expected_status": 401}, ), MockCityHostileFixture( area="idp", scenario="clock_skew_not_before", target="Brookfield Keycloak", - trigger="token nbf is ahead of CivicClerk's host clock", + trigger="token nbf is ahead of CivicMeetings' host clock", expected_behavior="reject with 401 and point the operator at clock synchronization", - fix="Check clock synchronization between CivicClerk and the IdP, then refresh the access token.", + fix="Check clock synchronization between CivicMeetings and the IdP, then refresh the access token.", sample={"provider_family": "keycloak", "claim": "nbf", "expected_status": 401}, ), MockCityHostileFixture( @@ -299,7 +299,7 @@ def mock_city_backup_retention_hostile_fixtures() -> list[MockCityHostileFixture def mock_city_hostile_fixtures() -> list[MockCityHostileFixture]: - """Return every hostile-mode fixture exposed by the CivicClerk mock-city suite.""" + """Return every hostile-mode fixture exposed by the CivicMeetings mock-city suite.""" return ( mock_city_idp_hostile_fixtures() @@ -309,7 +309,7 @@ def mock_city_hostile_fixtures() -> list[MockCityHostileFixture]: def run_mock_city_idp_contract_suite() -> list[MockCityIdpCheck]: - """Validate CivicClerk's mock municipal IdP contract without contacting an IdP.""" + """Validate CivicMeetings' mock municipal IdP contract without contacting an IdP.""" contract = mock_city_idp_contract() config = _mock_city_oidc_config(contract) diff --git a/civicclerk/models.py b/civicclerk/models.py index 3f9a9dd..92cbc9f 100644 --- a/civicclerk/models.py +++ b/civicclerk/models.py @@ -1,4 +1,4 @@ -"""CivicClerk canonical schema metadata.""" +"""CivicMeetings canonical schema metadata.""" from __future__ import annotations diff --git a/civicclerk/motion_vote.py b/civicclerk/motion_vote.py index 739c56e..2f680cf 100644 --- a/civicclerk/motion_vote.py +++ b/civicclerk/motion_vote.py @@ -1,4 +1,4 @@ -"""Motion, vote, and action-item capture helpers for CivicClerk.""" +"""Motion, vote, and action-item capture helpers for CivicMeetings.""" from __future__ import annotations diff --git a/civicclerk/oidc_auth.py b/civicclerk/oidc_auth.py index d5e3fbb..b3f6a0f 100644 --- a/civicclerk/oidc_auth.py +++ b/civicclerk/oidc_auth.py @@ -1,4 +1,4 @@ -"""OIDC bearer-token validation for CivicClerk staff routes.""" +"""OIDC bearer-token validation for CivicMeetings staff routes.""" from __future__ import annotations @@ -123,7 +123,7 @@ def authorize_oidc_staff_token( raise HTTPException( status_code=503, detail={ - "message": "CivicClerk OIDC staff auth is not configured.", + "message": "CivicMeetings OIDC staff auth is not configured.", "fix": _missing_config_fix(missing, env_names), }, ) @@ -166,7 +166,7 @@ def authorize_oidc_staff_token( detail={ "message": "OIDC token is not valid yet.", "fix": ( - "Check clock synchronization between CivicClerk and the municipal identity " + "Check clock synchronization between CivicMeetings and the municipal identity " "provider, then refresh the access token before retrying." ), }, @@ -195,7 +195,7 @@ def authorize_oidc_staff_token( "message": "OIDC identity lacks an allowed staff role.", "fix": ( "Map the identity provider app role or group claim to one of the " - "CivicClerk staff roles before retrying." + "CivicMeetings staff roles before retrying." ), "required_roles": sorted(normalized_allowed), "principal_roles": sorted(principal_roles), @@ -251,7 +251,7 @@ def authorize_oidc_staff_session_cookie( allowed_roles: Iterable[str], env_names: dict[str, str], ) -> AuthenticatedPrincipal: - """Validate a signed CivicClerk browser session cookie for OIDC staff routes.""" + """Validate a signed CivicMeetings browser session cookie for OIDC staff routes.""" if not session_cookie: raise HTTPException( @@ -292,7 +292,7 @@ def authorize_oidc_staff_session_cookie( status_code=401, detail={ "message": "OIDC browser session could not be validated.", - "fix": "Clear the CivicClerk staff session cookie, sign in again, and confirm the session secret has not changed.", + "fix": "Clear the CivicMeetings staff session cookie, sign in again, and confirm the session secret has not changed.", }, headers={"WWW-Authenticate": "Bearer"}, ) from exc @@ -305,7 +305,7 @@ def authorize_oidc_staff_session_cookie( status_code=403, detail={ "message": "OIDC browser session lacks an allowed staff role.", - "fix": "Ask IT to map the identity provider app role or group claim to a CivicClerk staff role, then sign in again.", + "fix": "Ask IT to map the identity provider app role or group claim to a CivicMeetings staff role, then sign in again.", "required_roles": sorted(normalized_allowed), "principal_roles": sorted(principal_roles), }, @@ -373,4 +373,4 @@ def _missing_config_fix(missing: Iterable[str], env_names: dict[str, str]) -> st "algorithms": env_names["algorithms"], } needed = ", ".join(labels[item] for item in missing) - return f"Set {needed} before exposing CivicClerk staff routes in OIDC mode." + return f"Set {needed} before exposing CivicMeetings staff routes in OIDC mode." diff --git a/civicclerk/packet_notice.py b/civicclerk/packet_notice.py index 0ed919c..afedad2 100644 --- a/civicclerk/packet_notice.py +++ b/civicclerk/packet_notice.py @@ -1,4 +1,4 @@ -"""Packet snapshot, export bundle, and notice compliance helpers for CivicClerk.""" +"""Packet snapshot, export bundle, and notice compliance helpers for CivicMeetings.""" from __future__ import annotations diff --git a/civicclerk/prompt_evals.py b/civicclerk/prompt_evals.py index fe329b2..692a090 100644 --- a/civicclerk/prompt_evals.py +++ b/civicclerk/prompt_evals.py @@ -1,4 +1,4 @@ -"""Offline prompt evaluation harness for CivicClerk prompt YAML files.""" +"""Offline prompt evaluation harness for CivicMeetings prompt YAML files.""" from __future__ import annotations diff --git a/civicclerk/prompt_library.py b/civicclerk/prompt_library.py index 0efd5df..5c6f04f 100644 --- a/civicclerk/prompt_library.py +++ b/civicclerk/prompt_library.py @@ -79,7 +79,7 @@ def load_prompt(prompt_id: str) -> PromptDefinition: prompt_path = PROMPTS_DIR / f"{prompt_id}.yaml" if not prompt_path.exists(): raise PromptLibraryError( - f"Prompt '{prompt_id}' is not present in the CivicClerk YAML prompt library." + f"Prompt '{prompt_id}' is not present in the CivicMeetings YAML prompt library." ) return _parse_prompt_yaml(prompt_path.read_text(encoding="utf-8")) @@ -171,7 +171,7 @@ def expected_prompt_version_hint(prompt_id: str = "minutes_draft") -> str: def _parse_prompt_yaml(raw: str) -> PromptDefinition: - """Parse the limited YAML shape used by CivicClerk prompt files.""" + """Parse the limited YAML shape used by CivicMeetings prompt files.""" lines = raw.splitlines() scalar_values: dict[str, str] = {} required_variables: list[str] = [] @@ -287,7 +287,7 @@ def scalar_one_or_none(self): def _remove_civiccore_prompt_tables_from_shared_metadata() -> None: - # CivicClerk intentionally exposes only the canonical civicclerk schema in + # CivicMeetings intentionally exposes only the canonical civicclerk schema in # shared metadata; the CivicCore resolver ORM tables are owned by CivicCore. for table_name in ("prompt_templates", "model_registry"): table = CivicCoreBase.metadata.tables.get(table_name) diff --git a/civicclerk/public_ui.py b/civicclerk/public_ui.py index 6f1d54a..eaf622c 100644 --- a/civicclerk/public_ui.py +++ b/civicclerk/public_ui.py @@ -1,4 +1,4 @@ -"""Accessible resident-facing public portal shell for CivicClerk.""" +"""Accessible resident-facing public portal shell for CivicMeetings.""" from __future__ import annotations @@ -12,7 +12,7 @@ def render_public_portal() -> str: - CivicClerk Public Portal + CivicMeetings Public Portal