Commit Graph

800 Commits

Author SHA1 Message Date
Scott Idem
35fa5132e7 feat(event_badge): add Splash (Cvent) XLSX badge import endpoint
Adds POST /event/{event_id}/badge/import/splash_xlsx to handle
Splash registrant XLSX exports for Axonius DC 2026 and future events.
Includes _split_full_name helper for splitting 'Full Name' into
given/family name components.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 10:27:59 -04:00
Scott Idem
221854df90 feat(idaa): server-side Novi member verification endpoint
Proxies GET /customers/{uuid} to Novi AMS server-to-server so members'
browser IPs are no longer in the call path, eliminating false "Access
Denied" for users on hotel/conference WiFi, VPNs, and CDN-filtered nets.

- New router: GET /v3/action/idaa/novi_member/{uuid}
- Business logic in app/methods/idaa_novi_verify_methods.py
  - Redis cache (4h TTL, key: idaa:novi_member:{uuid})
  - 404 never cached (recently-joined member anti-pattern)
  - Email space→+ normalization (Novi quirk)
  - Display name: "FirstName L." format with Name field fallback
- Registered in registry.py under /v3/action/idaa tag
- 9 unit tests covering all response paths (200/404/429/503/unreachable,
  cache hit, email normalization, display name format)
- Frontend guide (Section 12) and tests/README updated with full spec
  and migration table for frontend hand-off

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 18:35:01 -04:00
Scott Idem
c64c3bc55a fix(importing): normalize non-breaking spaces in CSV datetime fields
Google Sheets embeds \xa0 (non-breaking space) in 12-hour time values
(e.g. "3:00\xa0PM") and when date/time columns are combined. This caused
MariaDB datetime INSERTs to fail with an OperationalError.

Adds _clean_datetime() which strips \xa0, normalizes whitespace, and
parses common import formats (M/D/YYYY H:MM AM/PM, etc.) into
YYYY-MM-DD HH:MM:SS before the DB write. Applied to all four datetime
fields: session and presentation start/end.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 10:15:13 -04:00
Scott Idem
44e4f5c4e6 feat: migrate email send to V3 action; deprecate api.py legacy endpoints
- Add /v3/action/email/send router (api_v3_actions_email.py) replacing /util/email/send
- Disable util_email router in registry; register new email action router
- Mark /api/request_jwt and /api/temp_token as deprecated (TODO: remove)
- Guide: add §8 Email Send Action, mark Axonius section EXPIRED, renumber §9-§11

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 14:44:28 -04:00
Scott Idem
b590bc09a0 fix: require root_url on email_auth_key_url; correct frontend guide for user auth endpoints
- Make root_url a required query param on GET /v3/action/user/{id}/email_auth_key_url
  (previously Optional[str]=None, which produced a malformed link in the emailed URL)
- Update GUIDE__AE_API_V3_for_Frontend.md: document root_url as required, add magic link
  URL format, note valid_email=True side effect, add 404 error, expand 403 conditions
  for authenticate, add 400 for verify_password when no password is set
- Add test_e2e_v3_user_action_routes.py and test_e2e_v3_user_auth_routes.py to tests/README.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 12:34:49 -04:00
Scott Idem
8f1fe5d4df Fixing this:
#3 (zombie import) is genuinely a 2-line fix — remove the import from api.py:10 and move db_connection.py to trash. Zero functional change since db is only in a commented-out line.
2026-04-16 20:09:12 -04:00
Scott Idem
c0626e061e fix: remove account_id injection from nested POST handler
Child objects in the nested endpoint inherit account context from their
parent via the FK relationship and do not carry their own account_id
column (e.g. event_badge, journal_entry). Injecting account_id into
data_to_insert would cause INSERT failures for any child whose table
has no account_id column but whose model has the field (from the view).

The original code set account_id in obj_data before model instantiation,
where the root_validator immediately stripped it — a harmless no-op.
The previous commit turned that dead line into a live injection by moving
it after serialization, which would break journal_entry creates on
non-bypass auth. Removed entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 20:22:20 -04:00
Scott Idem
dfb5289188 fix: skip account_id injection when model excludes it from DB writes
After the sanitize_payload order fix, account_id was being re-injected
into data_to_insert for models that explicitly list account_id in
fields_to_exclude_from_db (e.g. event_badge, event_device). Those tables
have no account_id column, causing INSERT failures.

Guard the post-sanitize account_id injection in both api_crud_v3.py and
api_crud_v3_nested.py by checking fields_to_exclude_from_db first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 19:09:11 -04:00
Scott Idem
0ecc5a97d5 fix: resolve secondary FKs in nested POST (event_badge_template_id)
In the nested POST handler (api_crud_v3_nested.py), sanitize_payload was
running before model instantiation. For secondary FK fields like
event_badge_template_id, sanitize_payload resolved the random string →
integer, then the model's root_validator stripped the integer back to None
(Vision ID anti-leakage guard). Only the parent FK survived because it was
explicitly re-injected after serialization.

Fix: moved sanitize_payload to run on data_to_insert after serialization,
matching the flat V3 POST pattern (api_crud_v3.py). Also moved account_id
injection to after sanitize_payload, fixing a latent bug where account_id
was silently written as NULL on non-bypass auth.

Adds regression test to test_e2e_v3_demo_parity.py that creates an
event_badge via nested POST with event_badge_template_id and verifies the
field is non-None in the response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 19:00:51 -04:00
Scott Idem
7f9666dc1e fix: authenticate_passcode — priority ordering, full role flags, per-role TTL, min_length 2026-04-10 11:53:58 -04:00
Scott Idem
ea25bf78d4 import: map marketing consent CSV column to event_badge.agree_to_tc and allow_tracking 2026-04-07 19:59:51 -04:00
Scott Idem
2659047d24 fix: sql_update record_id missing on Vision ID models — update path now works
All create_update_*_v4 functions for event_badge, event_person,
event_person_profile, event_presenter, and event_presentation were
calling sql_update without record_id. Vision ID models use Optional[str]
IDs with a root_validator that strips integer values, so the serialized
dict contained no id key and sql_update could not identify the row.

Fix: pass record_id=<integer_id> explicitly to sql_update in all five
functions. Also fix walrus-operator false-negative: None return from
sql_update (0 rows affected — record unchanged) is not an error and
should not abort sub-object cascade; use explicit `is False` check.

Also broadens Axonius badge_type_code mapping to substring match so
future ticket name variants still resolve correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 16:50:04 -04:00
Scott Idem
18374f855f event: Zoom CSV import — temporary Axonius badge_type_code mapping (attendee/sponsor) 2026-04-07 15:36:23 -04:00
Scott Idem
e35fdb4f67 event: Zoom CSV import — finalize mapping and cleanup (staged changes) 2026-04-07 13:02:34 -04:00
Scott Idem
987b552157 event: Zoom CSV import — check for existing event_person by event_id+external_id before create; handle duplicates 2026-04-07 11:41:54 -04:00
Scott Idem
7ad158883a event: Zoom CSV import — force registrant email as external_id; ignore placeholder Unique identifier 2026-04-07 11:35:28 -04:00
Scott Idem
2b608d7a1a event: Zoom CSV import — default Axonius badge template 21 (temporary) 2026-04-07 11:23:36 -04:00
Scott Idem
535fc9f2b5 event: Zoom CSV import — use email as fallback external_id; populate address/phone fields 2026-04-07 10:58:08 -04:00
Scott Idem
8e9fb88e5a General file clean up. 2026-04-02 17:10:35 -04:00
Scott Idem
b5c50fd116 Changed the expiration time from 1 hour to 2 hours. 2026-04-02 15:57:36 -04:00
Scott Idem
2a1f270db6 feat(jitsi): add JWT token E2E test suite and improve api.py comments
- Add tests/e2e/test_e2e_jitsi_token.py: verifies moderator/attendee claims,
  room isolation, input validation, and exp claim correctness
- Update Jitsi section comment in api.py with actionable secret rotation TODO
  (must update JWT_APP_SECRET here AND in dgr_zone_jitsi .env, then restart
  prosody + jicofo)
2026-04-02 12:57:44 -04:00
Scott Idem
ebc5db96da fix(jitsi): allow non-moderators to request Jitsi tokens
Removed the 403 guard that blocked non-moderators. is_moderator is
already passed through to the token payload, so participants get
"moderator": false as expected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 17:46:27 -04:00
Scott Idem
293f447a1c chore(site_domain): flesh out TODO stubs in legacy lookup routes
Uncommented and completed access_key + referrer handling in
lookup_site_domain_fqdn() and the GET /site/domain/fqdn/{fqdn} route.
These routes are disabled in registry.py and not currently active.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 14:48:28 -04:00
Scott Idem
4629e1ec63 feat(site_domain): restore access_key enforcement for FQDN lookups
- api_crud_v3: strip falsy access_key values; restrict keyless queries
  to public domains (both site_access_key and site_domain_access_key
  must be NULL/empty); 75-line recursive block replaced with ~16 lines
- lib_sql_search: expand virtual 'access_key' field into priority SQL —
  site_access_key first, site_domain_access_key as fallback
- cms.py: add site_domain_access_key to site_domain searchable_fields
- docs: update frontend guide with access key behavior and examples
- e2e test: expand to cover all valid/invalid access key scenarios (15/15)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 14:46:33 -04:00
Scott Idem
7f87f32b70 Add INFO logging for nested parent-resolution and add E2E nested-create test for event_badge 2026-03-27 11:30:08 -04:00
Scott Idem
687472f4e3 feat(user): V3 action endpoints + auth bug fixes (19/19 + 22/22 tests)
New router: /v3/action/user/ (api_v3_actions_user.py)
  - POST /authenticate  — credentials in body (not query params; security fix)
  - POST /verify_password
  - POST /{user_id}/change_password  — optional current-password verification
  - GET  /{user_id}/new_auth_key
  - GET  /{user_id}/email_auth_key_url
  Registered in registry.py under /v3/action/user with V3 AccountContext auth.

Bug fixes (from audit in previous session):
  - user.py: fix broken @router.get decorator (authenticate was unreachable)
  - user.py + user_methods.py: fix AttributeError id_random → id (Vision ID)
  - user_models.py: add fields_to_exclude_from_db to User_New_Base; narrow
    collision prevention to self-reference IDs only
  - user_models.py: pre-inject hashed password in root_validator(pre=True) so
    exclude_unset=True in CRUD POST handler includes it (was writing NULL)
  - api_crud_v3.py: move sanitize_payload + account_id injection to after
    model validation (fixes FK integer collision with Vision ID constraints)

Docs: GUIDE__AE_API_V3_for_Frontend.md — new Section 7 with full migration
  table (legacy → V3), request/response docs for all 5 action endpoints,
  and V3 CRUD search equivalents for the 3 lookup routes.

Tests: tests/e2e/test_e2e_v3_user_action_routes.py — 19 tests, 19/19 pass.
  Legacy tests/e2e/test_e2e_v3_user_auth_routes.py — 22/22 still pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 21:54:09 -04:00
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
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
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
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
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
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
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
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
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
9d89d4c8e4 fix: exclude account_id and virtual fields from archive_content DB writes
- Adds fields_to_exclude_from_db to Archive_Content_Base to prevent SQL errors on non-existent columns.
- Updates documentation for V3 Create/Update patterns and the x-ae-ignore-extra-fields header.
- Propagates account_id_random to hosted file and media processing methods.
2026-02-24 11:30:17 -05:00
Scott Idem
48fc97cf46 feat: add priority filtering and sort stability to V3 Lookup System 2026-02-20 17:18:21 -05:00
Scott Idem
6bfbff309a feat: implement V3 Uniform Lookup System with hierarchical overrides and site-based whitelisting 2026-02-20 14:48:50 -05:00
Scott Idem
17a627a981 feat: Implement Event File Hosted Data Fix and API Guide Update
Address critical data visibility issues for Event Files and enhance frontend documentation.

This commit resolves the persistent problem where top-level hosted file convenience fields
(e.g., , , ) were
returning as  in V3 Event File API responses, even when .

Key changes include:
- Refactored  Pydantic model:
    - Removed redundant  definitions from top-level hosted file convenience fields,
      allowing direct mapping from SQL view columns.
    - Simplified  to focus solely on conditionally loading the nested
       object, as top-level fields are now populated directly by Pydantic
      from the  view.
    - Added comprehensive comments to clarify data flow, Pydantic's behavior, and the
      expected origin of these convenience fields from SQL views.
- Updated :
    - Introduced a new section detailing how to retrieve Event File data, including the
      use of  to get both top-level convenience fields and a nested
       object.
    - Clarified all ID references as random string IDs.
    - Renumbered the troubleshooting section.
- Copied updated guide to .
- Continued ID Vision compliance audit, ensuring consistent handling of random string IDs
  across various core and event models (Account, Address, Contact, DataStore, Event Badge Template).
- Consolidated ID Vision E2E tests and updated related documentation.
- Minor updates to  and
  to support Event File data retrieval with .
2026-02-19 15:22:17 -05:00
Scott Idem
2266f149f7 security(v3): harden multi-tenant isolation and enhance failure feedback 2026-02-13 18:45:20 -05:00
Scott Idem
68e883ba98 feat(v3-data-store): harden search security and standardize test suite 2026-02-09 19:03:04 -05:00
Scott Idem
8270f7ff7a fix(v3-actions): implement from_hosted_file and harden vision IDs
1. Implemented specialized 'from_hosted_file' action for Event Files.\n2. Fixed ValueError in Pydantic models by removing default/default_factory conflict.\n3. Hardened integer stripping to strictly enforce Vision Standards.\n4. Updated documentation for the new action route.
2026-02-06 16:23:18 -05:00
Scott Idem
b63131e3fa fix(v3-nested): support aliases in nested CRUD routes
1. Added 'entry' alias for 'journal_entry' in object definitions.\n2. Updated nested router to resolve physical table names from the registry before ID resolution.\n3. Updated ID resolution helpers to recognize 'entry' prefix.\nThis resolves 404 errors when using shorter aliases in nested paths (e.g., /journal/{id}/entry/).
2026-02-06 14:13:22 -05:00
Scott Idem
37a43babb9 fix(v3-actions): fix UnicodeEncodeError in download filenames
Hardened StreamingResponse headers to use RFC 6266 filename* parameter with UTF-8 encoding. This prevents the latin-1 codec crash when filenames contain non-ASCII characters like smart quotes.
2026-02-06 10:44:22 -05:00