feat: block 1 models, tenancy, and event registry - #118
Merged
Conversation
…gistry Foundation for the Django rebuild (mvp-plan block 1). Data model only -- no service layer, Host-resolution middleware or first-run wizard yet; those are the next PRs. Models - tenants: Operator (AUTH_USER_MODEL), Tenant, StaffMembership, OperatorInvite. Principals and structure -- not tenant-scoped. - directory: ListingType, Category, Listing, DirectoryUser, Claim, Lead, Consent, ConsentText, SuppressionKey, ImportBatch. - billing: Tier, Entitlement. - audit: OutboxEvent, CommandLog, AccessLog. Tenancy layer - osds.tenancy: ContextVar current-tenant scope plus tenant_context(). - osds.db.TenantScopedManager: declared first as `objects`, so it is the default manager; raises NoTenantInScope when no tenant is set. `_base_ manager` is left unscoped; `all_tenants` is the plain, greppable escape hatch. - tenants/tests/test_scoped_manager.py asserts the wiring across every app, with StaffMembership, CommandLog and AccessLog allowlisted and the reason recorded in the test. Event registry - audit/events.py: the 77 event-type constants from spec 3.3 and the flat ALL_EVENT_TYPES frozenset. media.* and search.* stay deferred. - audit/tests/test_event_types.py keeps the constants and the set in lockstep and pins the catalogue to the spec. Decisions applied: geo_precision "none" iff lat and lon are both null (CheckConstraint); OutboxEvent.tenant NOT NULL (the envelope still omits the block for tenant.* events); AccessLog.tenant nullable; Listing.current_tier is a denormalised FK written only by the entitlement service; full 26-char ULIDs for every prefix; slug unique on (tenant, listing_type); no Entitlement.slot FK yet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L5qqrLcxpVZRis5jbN5pKD Signed-off-by: Matthew Wren <info@origindev.com>
Settings built the database config from a hard-coded SQLite path and ignored DATABASE_URL entirely -- so the Postgres service CI provisions was never used, and the schema had only ever been exercised on SQLite. DATABASE_URL is now the sole source: parsed with urllib, engine pinned to django.db.backends.postgresql (psycopg 3, already in requirements). No SQLite, no fallback, no conditional -- the process fails at import if DATABASE_URL is unset. CI already sets it; the compose file (next PR) will too. Verified against PostgreSQL 16: `migrate` from an empty database, `makemigrations --check --dry-run` (no changes), and the full suite (18 tests) all pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L5qqrLcxpVZRis5jbN5pKD Signed-off-by: Matthew Wren <info@origindev.com>
- new_ulid(): 26 characters, Crockford base32 only, leading char within 128 bits, no collisions over 20k draws, and lexicographic order matches mint order across milliseconds. - Each `<entity>_id` factory prepends its own prefix to a 26-char ULID; prefixes are distinct; a guard test fails if a factory is added to osds/ids.py without being covered here. No assertion on within-millisecond ordering -- the low 80 bits are random by design and the factory is intentionally not monotonic. Plain unittest.TestCase (no database); also runs under `manage.py test`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L5qqrLcxpVZRis5jbN5pKD Signed-off-by: Matthew Wren <info@origindev.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
19 models across tenants/directory/billing/audit. Tenant-scoped default manager raising NoTenantInScope, with the manager test and its allowlist. 77-entry event-name registry with its test. Settings wired to DATABASE_URL; the suite previously ran on SQLite in CI despite the Postgres service being provisioned. Verified from zero on Postgres 16.