Commit Graph

1338 Commits

Author SHA1 Message Date
Scott Idem
91434968f7 docs+site_domain: Add guidance for restoring access_key validation in site_domain lookup; stage recent user/auth changes and frontend guide updates 2026-03-25 19:33:53 -04:00
Scott Idem
6bde236633 fix(crud): extend Vision ID safety net to all response paths
- Extracted apply_vision_id_fix() helper to lib_api_crud_v3.py — single
  source of truth for the fix that ensures {obj_type}_id in responses is
  always the random string, never the DB integer.
- Applied to all response-returning paths in api_crud_v3.py:
  GET single, GET list, POST search, POST create, PATCH update.
- Applied to all response-returning paths in api_crud_v3_nested.py:
  GET child list, POST search, POST create, GET single child, PATCH child.
- Removed duplicate get_child_obj and patch_child_obj route handlers in
  api_crud_v3_nested.py — FastAPI silently routes to only the first
  matching handler, so the second definitions were unreachable dead code.

Covers all 23 V3 CRUD models still using the old integer-alias pattern.
The archive_content model was already migrated to Vision IDs; this fix
ensures every other model gets correct responses without individual migration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 18:35:21 -04:00
Scott Idem
cffde249d3 fix(models): migrate Archive_Content_Base to Vision ID pattern
- Replace integer `id` (alias archive_content_id) with Vision string fields:
  `id: Optional[str]` and `archive_content_id: Optional[str]` — both always
  hold the random string ID, never the DB integer.
- Add `root_validator(pre=True)` (map_v3_ids) that maps id_random /
  archive_content_id_random → id and archive_content_id, with collision
  prevention to reject any integer that arrives in these fields.
- Remove old `archive_content_id_lookup` integer validator (superseded by
  sanitize_payload + root_validator).
- Keep `id_random` (alias archive_content_id_random) in responses for
  backward compatibility; add id, archive_content_id, id_random to
  fields_to_exclude_from_db so they never appear in INSERT/UPDATE payloads.

Generic CRUD layer safety net (post_obj + post_child_obj):
- After building resp_data on create, swap any integer {obj_type}_id with
  the corresponding {obj_type}_id_random value — catches models not yet
  migrated to Vision IDs.
- Fix return_obj=False fallback to return obj_id as the random string.

Docs: add Section 3D to GUIDE__AE_API_V3_for_Frontend.md documenting the
Vision ID convention — {obj_type}_id is always the random string; the
_id_random suffix is a legacy artifact that frontend code should phase out.

Fixes: POST /v3/crud/archive/{id}/archive_content/ returning integer ID,
breaking the subsequent PATCH flow (422 min_length validation failure).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 17:40:27 -04:00
Scott Idem
9d5f2c8cea Version update 2026-03-25 13:26:11 -04:00
Scott Idem
b9742cfcd8 feat(routers): migrate hosted_file hash lookup to V3 actions
Ported the legacy '/hosted_file/hash/{hash}' endpoint to the V3 actions router.
The new endpoint '/v3/action/hosted_file/hash/{hosted_file_hash}' supports:
- ID Vision: returns random string IDs instead of internal integers
- Local Check: verifies physical file existence on disk (check_for_local=True)
- Deduplication: enables frontend to check for existing files before upload

Also added PROJECT document for AE Hosted Files migration tracking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:05:09 -04:00
Scott Idem
b2adfe409b fix(deps): pin gunicorn to 23.0.0
Newer gunicorn patch releases added _get_control_socket_path() which
crashes with TypeError when control_socket is None. Pin to the working
version until the gunicorn config fix propagates everywhere.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 20:23:41 -04:00
Scott Idem
b55b7ea81d refactor(routers): add DeprecationParams to legacy active endpoints
Tags remaining live-but-deprecated routes so every call logs a warning,
giving visibility before the next round of removals.

- registry.py: add DeprecationParams to importing and user routers
- api.py: add DeprecationParams to /request_jwt and /temp_token individually
- user.py: inherits deprecation warning via registry router-level dependency

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:33:31 -04:00
Scott Idem
8eb699efe5 refactor(routers): comment out legacy endpoints across multiple routers
Disabled legacy routes that are superseded by V3 equivalents. Code is
commented out (not deleted) pending final verification and cleanup pass.

- registry.py: remove sql, lookup (/lu), websockets, websockets_redis;
  clean up dead imports (contact, event_person, etc.)
- data_store.py: comment out legacy CRUD and code-lookup endpoints;
  keep V3 code-lookup routes active; add TODO for action path rename
- api.py: comment out Api_Base CRUD, get_id (internal ID leak),
  and sql_test (debug) endpoints
- aether_cfg.py: comment out legacy Flask cfg endpoint
- user.py: comment out legacy user endpoints
- util_email.py: minor cleanup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:22:45 -04:00
Scott Idem
c7f1341b1e docs(lookup): expand Section 4 with override model, group key invariants
Documents the root cause of the timezone collapse bug and how to avoid it
in future data imports. Covers:
- group as the dedup identity key (not a display label), per lookup type
- correct way to add/update/remove account and object overrides
- hard invariant for time_zone: group must equal name
- verification query to catch bad seed data before it ships
- frontend keying guidance: use group, not id or name

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:56:50 -04:00
Scott Idem
15b5084df3 Quick lookup project for time zones. 2026-03-23 17:50:59 -04:00
Scott Idem
c9ec3d7ea1 revert(lookup): restore PARTITION BY group; tests now track data fix
Reverts the PARTITION BY name change — group is the correct dedup key.
Partitioning by name broke country deduplication (two US records both
survived, causing Svelte each_key_duplicate on alpha_2_code='US').

Root cause is bad seed data in lu_v3_time_zone: group='United States'
for 13 US/* zones and group='Europe' for 63 Europe/* zones instead of
group=name. A separate DB UPDATE is required to fix those rows.

Tests updated to assert:
- No duplicate alpha_2_code in country list (PARTITION BY group regression)
- All 13 US/* and Europe/* spot-check zones present (pending DB data fix)
- priority-only timezone count == 72 (pending DB data fix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:31:30 -04:00
Scott Idem
ccf2f30e11 fix(lookup): partition dedup by name instead of group
ROW_NUMBER() was partitioning by `group`, collapsing all 12 US/* timezones
(which share group="United States") down to a single record. Partitioning
by `name` correctly deduplicates by timezone identity while still preserving
the object > account > global override hierarchy.

Priority-only list now returns the expected 72 entries. Adds a regression
test asserting all 12 US/* timezones are present in the full list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 16:46:47 -04:00
Scott Idem
f23d27de15 Updated gitignore to fix a problem when deploying in test, bak, and prod on Linode 2026-03-23 16:07:37 -04:00
Scott Idem
a0767b1c69 Saving documentation updates and clean up. 2026-03-18 16:16:58 -04:00
Scott Idem
356f4b8efc Docs: Modernize main README, archive legacy/deprecated guides, and mark completed security/project docs (March 2026 review) 2026-03-18 16:16:20 -04:00
Scott Idem
74ad69bc63 Saving updated to do list 2026-03-18 14:35:39 -04:00
Scott Idem
d7b86cc186 docs(todo): add Bitbucket app password → API token migration deadline
App passwords inactive 2026-06-09.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 19:24:05 -04:00
Scott Idem
9adf5659bc test(errors): add unit test for 1364 schema mismatch error
Covers the fix from 308a7f2 — verifies that MariaDB error 1364
is classified as database_schema and the field name is extracted
into a readable message.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 19:09:53 -04:00
Scott Idem
308a7f296f fix(errors): classify 1364 as database_schema with actionable message
Parses the field name from the MariaDB error and returns a clear
"Schema mismatch: column 'X' is NOT NULL..." message instead of the
raw DB string. Consistent with how 1054/1146 (unknown column/table)
are already handled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 18:39:50 -04:00
Scott Idem
950e34cabd docs: mark Novi-Mailman Bridge POC complete and update notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 18:17:18 -04:00
Scott Idem
6b25cf9c6d feat: add Novi AMS → Mailman 3 cron-based mirror sync bridge (IDAA)
Implements a full proof-of-concept for syncing IDAA's Novi AMS membership
groups to Mailman 3 mailing lists via a cron-triggered reconciliation approach.

Key changes:
- methods: rewrote sync engine around confirmed Novi API shape — group-based
  member fetch (/groups/{guid}/members + /customers/{uuid}), respects
  Active=false and UnsubscribeFromEmails=true flags
- methods: mirror_novi_group_to_mailman_list() diffs Novi group against
  Mailman roster and subscribes/unsubscribes accordingly (full mirror)
- methods: mirror_all_configured_mappings() iterates novi_mailman_sync
  config array in IDAA site cfg_json — this is the cron target
- router: replaced old /sync endpoint with POST /sync (all mappings) and
  POST /sync/group/{guid} (single mapping); removed webhook endpoint
  (sync is cron-based, not event-driven)
- router: added GET/POST/DELETE endpoints for list member inspection
  and manual subscribe/unsubscribe
- tests: two new e2e scripts covering connection checks and full member
  lifecycle; old webhook integration test archived

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 16:36:32 -04:00
Scott Idem
29579fd9f1 feat: add V3 action endpoint for event exhibit tracking export
- New router: app/routers/api_v3_actions_event_exhibit.py
  - GET /v3/action/event_exhibit/{exhibit_id}/tracking_export
  - Full V3 auth (x-aether-api-key + account context)
  - Multi-tenant ownership check via check_account_access
  - Permission gate: leads_api_access flag OR manager-level access
  - Returns CSV or XLSX file attachment (return_file=false for JSON)
  - Flattens responses_json custom Q&A columns; strips HTML from exhibitor_notes
  - Exports all records regardless of hidden/enabled state

- Registered in registry.py under prefix /v3/action/event_exhibit

- New E2E test: tests/e2e/test_e2e_v3_action_event_exhibit_tracking_export.py
  - 7/7 tests passing against dev-api.oneskyit.com

- Docs: GUIDE__AE_API_V3_for_Frontend.md — new Section 7 covering endpoint
  usage, columns, leads_api_access dual-purpose (3rd-party API + UI export gate)

- Docs: tests/README.md — added test to table and when-to-run matrix
2026-03-16 16:50:32 -04:00
Scott Idem
5f3ba1e03e Saving port clarification. 2026-03-16 12:41:29 -04:00
Scott Idem
eaa18a1d45 fix(nested-crud): re-inject parent FK after model serialization to prevent 1364 errors
Root cause: child model root_validators (Vision ID anti-leakage guard) strip
integer IDs before they can be serialized into the INSERT dict, causing MariaDB
to reject the INSERT with 'Field does not have a default value' (1364).

Fix: re-inject resolved_parent_id into data_to_insert after validated_obj.dict()
in post_child_obj(). This is safe — the integer was already verified against the
DB before model validation.

Affected (were all broken since ~2026-01-27):
  - journal/{id}/journal_entry/
  - event/{id}/event_session/
  - event/{id}/event_person/
  - event/{id}/event_registration/
  - event/{id}/event_presenter/
  - event/{id}/event_presentation/
  - event/{id}/event_location/
  - event/{id}/event_track/
  - event/{id}/event_device/
  - event/{id}/event_abstract/
  - event/{id}/event_badge/ (different symptom: NULL FK)

Tests: add nested create lifecycle regression tests to test_e2e_v3_demo_parity.py
  - POST + Vision check + DELETE for journal/journal_entry and event/event_session
  - All 9 checks passing (7s)

Docs: update tests/README.md with accurate demo_parity description and
  a 'When to Run Tests' matrix to prevent future gaps in coverage.
2026-03-16 12:39:45 -04:00
Scott Idem
ee28a4f26e fix: set case_sensitive=False in config to ensure environment variables are correctly injected on Linode/Staging. 2026-03-11 22:35:22 -04:00
Scott Idem
e608696ec8 Docs: WS guide - client_id is UUID v4 persisted in localStorage, not Date.now() 2026-03-11 19:03:16 -04:00
Scott Idem
c7c14e8047 Docs: fix WS guide - client_id/group_id are opaque strings, not required Vision IDs 2026-03-11 19:02:06 -04:00
Scott Idem
c30631cb7d Optimized by Gemini CLI... I hope. 2026-03-11 17:04:30 -04:00
Scott Idem
8f0e6c16bc TODO: queue WS V3 frontend test after IDAA work 2026-03-11 16:01:16 -04:00
Scott Idem
49952074aa Update WS router test: wire AccountContext mock, add heartbeat presence refresh test 2026-03-11 15:41:34 -04:00
Scott Idem
32b519c507 V3 WebSocket: wire auth dependency, add heartbeat presence refresh, update frontend guide (wss://, auth query params, schema clarifications) 2026-03-11 15:21:19 -04:00
Scott Idem
8c7263fdbf Update docs: correct guide links in README, add March 11 session notes to TODO__Agents 2026-03-11 15:14:33 -04:00
Scott Idem
44fa28fab3 Robust delete: handle filesystem unlink errors in hosted file action 2026-03-11 15:01:41 -04:00
Scott Idem
a20c436013 Migrate clip/convert to V3 actions; add background clip support, redirect legacy route; update frontend guide 2026-03-11 14:51:08 -04:00
Scott Idem
fbbc186af0 feat: add convert_file endpoint to v3 actions hosted_file router
Exposes GET /v3/action/hosted_file/{id}/convert_file using AccountContext
(v3 auth pattern) alongside the legacy /hosted_file/ route. Accepts
link_to_type, link_to_id, filename_no_ext, and to_type query params.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 14:26:40 -04:00
Scott Idem
57195bca30 chore: Added .dockerignore to optimize build context size. 2026-03-11 12:36:34 -04:00
Scott Idem
03be0ac062 Version bump to 3.00.01 2026-03-11 09:37:41 -04:00
Scott Idem
f110c2eecb docs: Expand TODO with Novi-Mailman bridge details and session notes
- Add confirmed Novi API patterns (auth, field names, endpoints)
- List remaining unknowns and data_store credential setup requirements
- Add pydantic/SQLAlchemy migration notes
- Summarize completed operational hardening and BuildKit cache work

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 19:30:01 -04:00
Scott Idem
3111ed5f22 fix: Correct Novi API auth header and field names in Mailman bridge
- Auth: ApiKey header → Authorization: Basic (confirmed from IDAA Jitsi code)
- Member fields: confirmed PascalCase (FirstName, LastName, Email) from Novi API
- email.replace(' ', '+') to match Jitsi's sanitization pattern
- Bulk member list endpoint marked TODO pending confirmation
- Response unwrapping handles Results/Members/value/array shapes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 19:26:36 -04:00
Scott Idem
f1c8958a7a feat: Scaffold Novi-Mailman Bridge integration
- app/methods/e_novi_mailman_methods.py: full sync engine, per-member
  sync helper, webhook handler, and Mailman 3 REST subscribe/unsubscribe
- app/routers/api_v3_actions_e_novi_mailman.py: test_connection, list
  inspection, full sync trigger, and Novi webhook receiver endpoints
- registry.py: registered at /v3/action/e_novi_mailman
- TODO: marked as scaffolded, pending Novi field verification + data_store setup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 19:16:16 -04:00
Scott Idem
42aa318ba0 chore: Prune 4 transitive deps from requirements.txt
Removed MarkupSafe, rfc3986, sniffio, starlette — all pulled in
automatically as transitive dependencies of fastapi/httpx/anyio.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 18:58:39 -04:00
Scott Idem
fc3277086f feat: Add BuildKit pip cache, unlock fastapi pin, mark Locking TODO complete
- Dockerfile: enable BuildKit syntax, use --mount=type=cache for pip to speed up rebuilds
- requirements.txt: relax fastapi==0.115.5 → fastapi>=0.115.5
- TODO: mark Locking task as complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 18:53:54 -04:00
Scott Idem
32560d2257 feat: Operational hardening — healthcheck, config refactor, requirements lock
- Add GET /health route (DB + Redis ping, 200/503) with Dockerfile HEALTHCHECK directive
- Replace config.py stub with real pydantic BaseSettings reading directly from env vars;
  remove external config file mount from docker-compose
- Add requirements.lock (pip freeze snapshot for bit-identical builds)
- Untrack config.py globally but allow app/config.py via .gitignore negation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 18:44:58 -04:00
Scott Idem
d35f374a45 Renamed the todo file for agents. 2026-03-10 16:26:51 -04:00
Scott Idem
25de8b9400 docs: Updated local development setup to use requirements.txt in project root. 2026-03-10 15:29:54 -04:00
Scott Idem
7a6ccc2520 feat: Restored requirements.txt and Dockerfile to project root. Project is now self-contained for Docker builds. 2026-03-10 15:23:13 -04:00
Scott Idem
e41a6da575 docs: Clarified Docker configuration model in unified orchestration. 2026-03-10 13:33:39 -04:00
Scott Idem
89e12b9f97 fix: Resolve ID Vision conflicts and validation errors in Event Exhibit Tracking
- Modified 'sanitize_payload' to ignore 'external_person_id', preventing incorrect lookup attempts for email/passcode fields.
- Refined 'Event_Exhibit_Tracking_Base' to allow 'Union[int, str]' for relational IDs, bypassing string-length validation for internal integers.
- Adjusted root validator to preserve relational integers during POST/PUT operations while still stripping primary/account IDs for Vision-compliant READ views.
- Aligned model configuration with other V3 objects for consistency.
2026-03-03 17:08:34 -05:00
Scott Idem
403b543ed2 Added the duplex field and some other minor clean up 2026-03-02 19:49:19 -05:00
Scott Idem
bc78ac4c2e test: Add E2E test for V3 model refactoring verification
This commit introduces a new end-to-end test script  to validate the recent model refactoring changes.

The test suite performs two primary checks for a list of target objects:
- **ID Vision Compliance:** Verifies that all primary and foreign key fields are returned as string IDs, ensuring adherence to the V3 ID Vision standard.
- **Excluded Fields Stripping:** Attempts a PATCH operation with fields explicitly listed in  and verifies that these fields are not updated in the database, confirming the  mechanism functions as intended.

This test is essential for ensuring the stability and correctness of the API's interaction with the refactored models.
2026-02-24 16:22:19 -05:00