Files
hub/tasks/architecture/storage/resolve-org-dual-ownership.md
glm-5.1 2b63cda1c7 Setup repo: migrate architecture specs, code stubs, and tasks from alkhub_ts
Copy architecture docs, ADRs, storage domain specs, research, reviews,
and 56 storage architecture tasks from the alkhub_ts monorepo. Adapt for
standalone @alkdev/hub repo structure (src/ not packages/hub/).

Sanitize all sensitive information:
- Replace private IPs (10.0.0.1) with localhost defaults
- Remove internal server hostnames (dev1, ns528096)
- Replace /workspace/ private paths with npm package references
- Remove hardcoded credentials from examples
- Rewrite infrastructure.md without private network details

Add Deno project scaffolding: deno.json (pinned deps), .gitignore,
AGENTS.md, entry point. Migrate existing code stubs (crypto, config
types, logger) with updated import paths.
2026-05-25 10:56:32 +00:00

1.9 KiB

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
resolve-org-dual-ownership Resolve dual ownership model for organizations completed
resolve-sessions-accountid-cascade
narrow high component implementation

Description

Two competing ownership concepts with no documented relationship:

  1. organizations.ownerId — a single FK to one account (identity.md:44)
  2. organization_members.membershipLevel: "owner" — can exist on multiple rows (identity.md:58)

Can ownerId point to an account with membershipLevel: "member" (not "owner")? Can an org have zero members with membershipLevel: "owner" but a non-null ownerId? An implementer cannot determine which field is authoritative for ownership queries.

The resolution of sessions.accountId cascade (C01) affects this because if account deletion is enabled (nullable FKs), the org ownership transfer workflow depends on knowing which field is authoritative.

Acceptance Criteria

  • identity.md documents the invariant relating organizations.ownerId and organization_members.membershipLevel
  • One of the following invariants is chosen and documented:
    • "ownerId is always a member with membershipLevel: 'owner' (enforced by app logic). If all owner-level members are removed, ownerId must be transferred first."
    • "ownerId is the creator; membershipLevel: 'owner' is a separate authorization concept."
  • The account deletion workflow interacts correctly with the chosen invariant (e.g., RESTRICT on ownerId means account deletion blocked if account owns an org)
  • table-reference.md cascade rationale for organizations.ownerId → accounts.id (RESTRICT) is updated with the invariant reference

References

  • docs/reviews/storage-architecture-review-2026-04-21.md#C13
  • docs/architecture/storage/identity.md:44
  • docs/architecture/storage/identity.md:58

Notes

To be filled by implementation agent

Summary

To be filled on completion