Phase 3 Readiness — Resource Sharing Tasks (0a–9) — Actionable Plan (2025-10-06) #103

Closed
opened 2025-10-06 02:17:41 +00:00 by rwachters · 0 comments
rwachters commented 2025-10-06 02:17:41 +00:00 (Migrated from github.com)

Phase 3 Readiness — Resource Sharing Tasks (0a–9)

Reference: temp/Phase 3 Readiness Report.md (2025-10-06)

Checklist

  • Task 0a — Refactor AccessMode to inline value class (BLOCKING)
  • Task 0b — Add access_mode column to access tables (CRITICAL)
  • Task 1 — Add authentication to provider/model/settings routes (HIGH)
  • Task 2 — Implement "All Users" group
  • Task 3 — Create resource ownership & access DAOs
  • Task 4 — Create resource authorizers
  • Task 5 — Add authorization to routes (route-layer enforcement)
  • Task 6 — Update services for resource sharing (filtering by access)
  • Task 7 — Frontend: Public / Private resource indicators
  • Task 8 — Frontend: Admin controls for resource sharing
  • Task 9 — Testing & Integration

Executive summary

Phases 1 and 2 are complete. Phase 3 (Resource Sharing) is ready to start but several critical issues must be addressed first. This issue contains the actionable Task list 0a–9 extracted from the Phase 3 Readiness Report. Each task is in its own section with action items, affected files/symbols, acceptance criteria, priority and time estimate.


Task 0a — Backend: Refactor AccessMode to inline value class (BLOCKING)

Summary: Replace the rigid AccessMode enum with a type-safe inline value class that wraps a String, expose common modes in the companion object (e.g. AccessMode.READ, AccessMode.WRITE).

Action items:

  1. Create AccessMode inline value class in common module.
  2. Update ResourceAuthorizer interface to accept AccessMode.
  3. Update AuthorizationService interface & AuthorizationServiceImpl to use AccessMode.
  4. Update SessionResourceAuthorizer and GroupResourceAuthorizer to accept/use AccessMode.
  5. Update all route files to pass AccessMode.READ / AccessMode.WRITE where applicable.
  6. Add unit tests for the new AccessMode usage and ensure compile-time updates.
  7. Remove old AccessMode enum or provide a small adapter for migration/tests.

Affected files/symbols (examples):

  • common/src/commonMain/kotlin/eu/torvian/chatbot/common/api/AccessMode.kt (new)
  • server/.../service/security/authorizer/AccessMode.kt (delete/adapter)
  • ResourceAuthorizer.kt, AuthorizationService.kt, AuthorizationServiceImpl.kt
  • SessionResourceAuthorizer.kt, GroupResourceAuthorizer.kt
  • Route files that use AccessMode (e.g. configureGroupRoutes.kt, configureSessionRoutes.kt, configureMessageRoutes.kt)

Acceptance criteria:

  • New inline AccessMode exists in common module with READ/WRITE constants.
  • All compile errors resolved; interfaces and implementations use new type.
  • Tests covering the new type pass.
  • No remaining use of the old enum in runtime paths (or explicit adapter exists).

Priority / Est.: ⚠️ BLOCKING — 2–3 days


Task 0b — Backend: Add access_mode column to access tables (CRITICAL)

Summary: Access tables currently track only which groups have access. Add an access_mode varchar column and include it in the composite primary key so multiple access modes per group/resource are possible.

Action items:

  1. Update LLMProviderAccessTable to add access_mode varchar(50) and include it in the primary key.
  2. Update LLMModelAccessTable similarly.
  3. Update ModelSettingsAccessTable similarly.
  4. Drop/recreate or migrate tables (the app is not in production — prefer recreate).
  5. Update seed/test data if present.

Affected files:

  • server/src/main/kotlin/eu/torvian/chatbot/server/data/tables/LLMProviderAccessTable.kt
  • server/src/main/kotlin/eu/torvian/chatbot/server/data/tables/LLMModelAccessTable.kt
  • server/src/main/kotlin/eu/torvian/chatbot/server/data/tables/ModelSettingsAccessTable.kt

Acceptance criteria:

  • Database schema (dev/test) includes access_mode on all three tables and composite PK includes it.
  • DAOs/queries that insert/check access are updated to read/write access_mode.
  • Tests validating read/write access per mode pass.

Priority / Est.: ⚠️ CRITICAL — 1–2 days


Task 1 — Backend: Add authentication to provider/model/settings routes (HIGH PRIORITY)

Summary: Several route modules are currently unauthenticated and must be protected.

Action items:

  1. Wrap configureProviderRoutes.kt routes in authenticate(AuthSchemes.USER_JWT) { ... }.
  2. Wrap configureModelRoutes.kt routes in authenticate(AuthSchemes.USER_JWT) { ... }.
  3. Wrap configureSettingsRoutes.kt routes in authenticate(AuthSchemes.USER_JWT) { ... }.
  4. Test unauthenticated requests are rejected (401) and authenticated requests work.

Affected files:

  • server/src/.../routes/configureProviderRoutes.kt
  • server/src/.../routes/configureModelRoutes.kt
  • server/src/.../routes/configureSettingsRoutes.kt

Acceptance criteria:

  • All provider/model/settings endpoints reject unauthenticated requests.
  • Existing clients with valid JWTs continue to work.

Priority / Est.: ⚠️ HIGH — 1 day


Task 2 — Backend: Implement "All Users" group

Summary: Provide a built-in "All Users" group to represent public resources; auto-assign new users to it; protect it from deletion/removal.

Action items:

  1. Update InitialSetupService to create the "All Users" group on setup and store its ID as a constant/config.
  2. Update UserService.registerUser() to auto-assign new users to "All Users" group.
  3. Add business rules to prevent deletion of the "All Users" group and prevent removing users from it.
  4. Add tests for the "All Users" lifecycle.

Affected files:

  • InitialSetupService (server)
  • UserService / UserService.registerUser()
  • UserGroups related DAO/services

Acceptance criteria:

  • "All Users" group exists after setup.
  • New users are automatically members of "All Users".
  • Attempts to delete or remove membership from "All Users" are rejected.

Priority / Est.: 2 days


Task 3 — Backend: Create resource ownership & access DAOs

Summary: Implement ownership DAOs and access DAOs for providers, models, and settings so authorizers can check owners and group-based access (including access mode).

Action items:

  1. Create ProviderOwnershipDao, ModelOwnershipDao, SettingsOwnershipDao with:
    • getOwner(resourceId): Either<GetOwnerError, Long>
    • setOwner(resourceId, userId): Either<SetOwnerError, Unit>
    • deleteOwner(resourceId): Either<DeleteOwnerError, Unit>
  2. Create ProviderAccessDao, ModelAccessDao, SettingsAccessDao with:
    • getAccessGroups(resourceId, accessMode: String): List<UserGroup>
    • hasAccess(resourceId, groupIds: List<Long>, accessMode: String): Boolean
    • grantAccess(resourceId, groupId, accessMode: String): Either<GrantAccessError, Unit>
    • revokeAccess(resourceId, groupId, accessMode: String): Either<RevokeAccessError, Unit>
    • getResourcesAccessibleByGroups(groupIds: List<Long>, accessMode: String): List<Long>
  3. Implement proper Either-based error handling and tests.

Affected files / packages: new DAO files under server/src/main/kotlin/.../dao (or existing DAO package).

Acceptance criteria:

  • DAOs provide the specified methods and behavior.
  • hasAccess respects the access_mode values stored in DB.
  • Unit tests for DAO behavior exist and pass.

Priority / Est.: 3–4 days


Task 4 — Backend: Create resource authorizers

Summary: Implement ProviderResourceAuthorizer, ModelResourceAuthorizer, SettingsResourceAuthorizer following the ResourceAuthorizer pattern (use AccessMode value class).

Action items:

  1. Create ProviderResourceAuthorizer that:
    • checks ownership first (owners have all access), then
    • checks group access using ProviderAccessDao.hasAccess(...) with the requested AccessMode
  2. Create ModelResourceAuthorizer and SettingsResourceAuthorizer similarly.
  3. Register the authorizers in Koin DI.
  4. Write unit tests for authorizer logic (owner vs group access vs deny).

Example method signature:

  • suspend fun requireAccess(userId: Long, resourceId: Long, accessMode: AccessMode): Either<ResourceAuthorizerError, Unit>

Affected files:

  • New *ResourceAuthorizer.kt files under service/security/authorizer
  • Koin module registration

Acceptance criteria:

  • Authorizers are registered and used by AuthorizationService.requireAccess().
  • Tests covering owner access, group access, and denied access pass.

Priority / Est.: 2–3 days


Task 5 — Backend: Add authorization to routes (route-layer enforcement)

Summary: Add requireAccess() route-layer checks for write operations and keep authorization at route layer (do not add userId to service methods).

Action items:

  1. Update configureProviderRoutes.kt:
    • Add requireAccess() checks for write operations (create/update/delete).
    • Use requirePermission() for admin-only actions.
  2. Update configureModelRoutes.kt similarly.
  3. Update configureSettingsRoutes.kt similarly.
  4. Ensure read operations are filtered by access where required.
  5. Add/keep consistent error mapping and status codes (e.g., 403 on access denied).

Affected files:

  • configureProviderRoutes.kt, configureModelRoutes.kt, configureSettingsRoutes.kt

Acceptance criteria:

  • Write operations are blocked for users without proper AccessMode.
  • Admin operations require appropriate permissions.
  • Tests demonstrate unauthorized users get 403 and authorized users succeed.

Priority / Est.: 2–3 days


Task 6 — Backend: Update services for resource sharing

Summary: Make service-layer methods that return lists filter by user access (ownership + group access) while keeping authorization checks in routes for write operations.

Action items:

  1. Update LLMProviderService.getAllProviders() to accept userId (or provide a filtering hook) and return only resources accessible to that user.
  2. Update LLMModelService.getAllModels() similarly.
  3. Update ModelSettingsService.getAllSettings() similarly.
  4. Add service methods for managing sharing (grant/revoke) if not already present (these can be invoked by admin routes).
  5. Add unit tests for filtered queries and sharing operations.

Affected files:

  • LLMProviderService, LLMModelService, ModelSettingsService and their implementations

Acceptance criteria:

  • GET/list endpoints only return resources the requesting user can access.
  • Sharing operations work via service/DAO and are covered by tests.

Priority / Est.: 2–3 days


Task 7 — Frontend: Public / Private resource indicators

Summary: Add UI indicators (badges) and ownership information so users can see whether a provider/model/settings is public (in "All Users") or private.

Action items:

  1. Add "Public" badge to ProviderListItem when provider is in "All Users" group.
  2. Add "Public" badge to ModelListItem when model is in "All Users" group.
  3. Add "Public" badge to SettingsListPanel when settings is in "All Users" group.
  4. Display ownership information in detail panels.

Affected files/components:

  • ProviderListItem, ModelListItem, SettingsListPanel, provider/model/settings detail panels.

Acceptance criteria:

  • Public resources visibly show a "Public" badge and ownership info in UI.
  • Badges update after sharing/unsharing actions.

Priority / Est.: 1–2 days


Task 8 — Frontend: Admin controls for resource sharing

Summary: Provide admin UI to make resources public or share with specific groups, with permission checks.

Action items:

  1. Add "Make Public" button to provider/model/settings detail panels (admin only).
  2. Add "Remove Public Access" button to undo.
  3. Create "Share with Group" dialog to select group(s) and access mode (read/write).
  4. Add permission checks for these operations (e.g. MANAGE_PUBLIC_RESOURCES).
  5. Wire UI to backend APIs (grant/revoke access endpoints).
  6. Add frontend tests (if applicable) and validations.

Affected files/components:

  • provider/model/settings detail panels, share dialog components, admin UI wiring.

Acceptance criteria:

  • Admins can make/unmake resources public.
  • Admins can share/unshare with groups specifying AccessMode.
  • UI reflects the new sharing status immediately (or after refresh).

Priority / Est.: 2–3 days


Task 9 — Testing & Integration

Summary: End-to-end verification of resource sharing, access enforcement, public access semantics, and admin controls.

Action items:

  1. End-to-end testing of resource sharing paths (owner, shared group, public).
  2. Test public resource access (users in "All Users" see public resources).
  3. Test private resource access restrictions (users without access cannot see or perform writes).
  4. Test admin controls (make public, share with group, revoke).
  5. Run performance checks for access checks (JOINs) and optimize queries if needed.
  6. Ensure unit/integration test coverage for new DAOs, authorizers, and services.

Acceptance criteria:

  • E2E tests confirm expected behavior for owner, group, public, and denied cases.
  • No regressions for sessions/groups admin features.

Priority / Est.: 2–3 days


If you'd like I can:

  • Create this issue now (I'll attach this content) and return the issue URL/number, or
  • Create a compact checklist version only, or
  • Start implementing Task 0a and open a PR draft.

Created from temp/Phase 3 Readiness Report.md (2025-10-06)

Phase 3 Readiness — Resource Sharing Tasks (0a–9) Reference: `temp/Phase 3 Readiness Report.md` (2025-10-06) Checklist - [ ] Task 0a — Refactor `AccessMode` to inline value class (BLOCKING) - [ ] Task 0b — Add `access_mode` column to access tables (CRITICAL) - [ ] Task 1 — Add authentication to provider/model/settings routes (HIGH) - [ ] Task 2 — Implement "All Users" group - [ ] Task 3 — Create resource ownership & access DAOs - [ ] Task 4 — Create resource authorizers - [ ] Task 5 — Add authorization to routes (route-layer enforcement) - [ ] Task 6 — Update services for resource sharing (filtering by access) - [ ] Task 7 — Frontend: Public / Private resource indicators - [ ] Task 8 — Frontend: Admin controls for resource sharing - [ ] Task 9 — Testing & Integration Executive summary Phases 1 and 2 are complete. Phase 3 (Resource Sharing) is ready to start but several critical issues must be addressed first. This issue contains the actionable Task list 0a–9 extracted from the Phase 3 Readiness Report. Each task is in its own section with action items, affected files/symbols, acceptance criteria, priority and time estimate. --- Task 0a — Backend: Refactor `AccessMode` to inline value class (BLOCKING) Summary: Replace the rigid `AccessMode` enum with a type-safe inline value class that wraps a `String`, expose common modes in the companion object (e.g. `AccessMode.READ`, `AccessMode.WRITE`). Action items: 1. Create `AccessMode` inline value class in common module. 2. Update `ResourceAuthorizer` interface to accept `AccessMode`. 3. Update `AuthorizationService` interface & `AuthorizationServiceImpl` to use `AccessMode`. 4. Update `SessionResourceAuthorizer` and `GroupResourceAuthorizer` to accept/use `AccessMode`. 5. Update all route files to pass `AccessMode.READ` / `AccessMode.WRITE` where applicable. 6. Add unit tests for the new `AccessMode` usage and ensure compile-time updates. 7. Remove old `AccessMode` enum or provide a small adapter for migration/tests. Affected files/symbols (examples): - `common/src/commonMain/kotlin/eu/torvian/chatbot/common/api/AccessMode.kt` (new) - `server/.../service/security/authorizer/AccessMode.kt` (delete/adapter) - `ResourceAuthorizer.kt`, `AuthorizationService.kt`, `AuthorizationServiceImpl.kt` - `SessionResourceAuthorizer.kt`, `GroupResourceAuthorizer.kt` - Route files that use `AccessMode` (e.g. `configureGroupRoutes.kt`, `configureSessionRoutes.kt`, `configureMessageRoutes.kt`) Acceptance criteria: - New inline `AccessMode` exists in common module with `READ`/`WRITE` constants. - All compile errors resolved; interfaces and implementations use new type. - Tests covering the new type pass. - No remaining use of the old enum in runtime paths (or explicit adapter exists). Priority / Est.: ⚠️ BLOCKING — 2–3 days --- Task 0b — Backend: Add `access_mode` column to access tables (CRITICAL) Summary: Access tables currently track only which groups have access. Add an `access_mode` varchar column and include it in the composite primary key so multiple access modes per group/resource are possible. Action items: 1. Update `LLMProviderAccessTable` to add `access_mode` varchar(50) and include it in the primary key. 2. Update `LLMModelAccessTable` similarly. 3. Update `ModelSettingsAccessTable` similarly. 4. Drop/recreate or migrate tables (the app is not in production — prefer recreate). 5. Update seed/test data if present. Affected files: - `server/src/main/kotlin/eu/torvian/chatbot/server/data/tables/LLMProviderAccessTable.kt` - `server/src/main/kotlin/eu/torvian/chatbot/server/data/tables/LLMModelAccessTable.kt` - `server/src/main/kotlin/eu/torvian/chatbot/server/data/tables/ModelSettingsAccessTable.kt` Acceptance criteria: - Database schema (dev/test) includes `access_mode` on all three tables and composite PK includes it. - DAOs/queries that insert/check access are updated to read/write `access_mode`. - Tests validating read/write access per mode pass. Priority / Est.: ⚠️ CRITICAL — 1–2 days --- Task 1 — Backend: Add authentication to provider/model/settings routes (HIGH PRIORITY) Summary: Several route modules are currently unauthenticated and must be protected. Action items: 1. Wrap `configureProviderRoutes.kt` routes in `authenticate(AuthSchemes.USER_JWT) { ... }`. 2. Wrap `configureModelRoutes.kt` routes in `authenticate(AuthSchemes.USER_JWT) { ... }`. 3. Wrap `configureSettingsRoutes.kt` routes in `authenticate(AuthSchemes.USER_JWT) { ... }`. 4. Test unauthenticated requests are rejected (401) and authenticated requests work. Affected files: - `server/src/.../routes/configureProviderRoutes.kt` - `server/src/.../routes/configureModelRoutes.kt` - `server/src/.../routes/configureSettingsRoutes.kt` Acceptance criteria: - All provider/model/settings endpoints reject unauthenticated requests. - Existing clients with valid JWTs continue to work. Priority / Est.: ⚠️ HIGH — 1 day --- Task 2 — Backend: Implement "All Users" group Summary: Provide a built-in "All Users" group to represent public resources; auto-assign new users to it; protect it from deletion/removal. Action items: 1. Update `InitialSetupService` to create the "All Users" group on setup and store its ID as a constant/config. 2. Update `UserService.registerUser()` to auto-assign new users to "All Users" group. 3. Add business rules to prevent deletion of the "All Users" group and prevent removing users from it. 4. Add tests for the "All Users" lifecycle. Affected files: - `InitialSetupService` (server) - `UserService` / `UserService.registerUser()` - `UserGroups` related DAO/services Acceptance criteria: - "All Users" group exists after setup. - New users are automatically members of "All Users". - Attempts to delete or remove membership from "All Users" are rejected. Priority / Est.: 2 days --- Task 3 — Backend: Create resource ownership & access DAOs Summary: Implement ownership DAOs and access DAOs for providers, models, and settings so authorizers can check owners and group-based access (including access mode). Action items: 1. Create `ProviderOwnershipDao`, `ModelOwnershipDao`, `SettingsOwnershipDao` with: - `getOwner(resourceId): Either<GetOwnerError, Long>` - `setOwner(resourceId, userId): Either<SetOwnerError, Unit>` - `deleteOwner(resourceId): Either<DeleteOwnerError, Unit>` 2. Create `ProviderAccessDao`, `ModelAccessDao`, `SettingsAccessDao` with: - `getAccessGroups(resourceId, accessMode: String): List<UserGroup>` - `hasAccess(resourceId, groupIds: List<Long>, accessMode: String): Boolean` - `grantAccess(resourceId, groupId, accessMode: String): Either<GrantAccessError, Unit>` - `revokeAccess(resourceId, groupId, accessMode: String): Either<RevokeAccessError, Unit>` - `getResourcesAccessibleByGroups(groupIds: List<Long>, accessMode: String): List<Long>` 3. Implement proper Either-based error handling and tests. Affected files / packages: new DAO files under `server/src/main/kotlin/.../dao` (or existing DAO package). Acceptance criteria: - DAOs provide the specified methods and behavior. - `hasAccess` respects the `access_mode` values stored in DB. - Unit tests for DAO behavior exist and pass. Priority / Est.: 3–4 days --- Task 4 — Backend: Create resource authorizers Summary: Implement `ProviderResourceAuthorizer`, `ModelResourceAuthorizer`, `SettingsResourceAuthorizer` following the `ResourceAuthorizer` pattern (use `AccessMode` value class). Action items: 1. Create `ProviderResourceAuthorizer` that: - checks ownership first (owners have all access), then - checks group access using `ProviderAccessDao.hasAccess(...)` with the requested `AccessMode` 2. Create `ModelResourceAuthorizer` and `SettingsResourceAuthorizer` similarly. 3. Register the authorizers in Koin DI. 4. Write unit tests for authorizer logic (owner vs group access vs deny). Example method signature: - `suspend fun requireAccess(userId: Long, resourceId: Long, accessMode: AccessMode): Either<ResourceAuthorizerError, Unit>` Affected files: - New `*ResourceAuthorizer.kt` files under service/security/authorizer - Koin module registration Acceptance criteria: - Authorizers are registered and used by `AuthorizationService.requireAccess()`. - Tests covering owner access, group access, and denied access pass. Priority / Est.: 2–3 days --- Task 5 — Backend: Add authorization to routes (route-layer enforcement) Summary: Add `requireAccess()` route-layer checks for write operations and keep authorization at route layer (do not add userId to service methods). Action items: 1. Update `configureProviderRoutes.kt`: - Add `requireAccess()` checks for write operations (create/update/delete). - Use `requirePermission()` for admin-only actions. 2. Update `configureModelRoutes.kt` similarly. 3. Update `configureSettingsRoutes.kt` similarly. 4. Ensure read operations are filtered by access where required. 5. Add/keep consistent error mapping and status codes (e.g., 403 on access denied). Affected files: - `configureProviderRoutes.kt`, `configureModelRoutes.kt`, `configureSettingsRoutes.kt` Acceptance criteria: - Write operations are blocked for users without proper `AccessMode`. - Admin operations require appropriate permissions. - Tests demonstrate unauthorized users get 403 and authorized users succeed. Priority / Est.: 2–3 days --- Task 6 — Backend: Update services for resource sharing Summary: Make service-layer methods that return lists filter by user access (ownership + group access) while keeping authorization checks in routes for write operations. Action items: 1. Update `LLMProviderService.getAllProviders()` to accept `userId` (or provide a filtering hook) and return only resources accessible to that user. 2. Update `LLMModelService.getAllModels()` similarly. 3. Update `ModelSettingsService.getAllSettings()` similarly. 4. Add service methods for managing sharing (grant/revoke) if not already present (these can be invoked by admin routes). 5. Add unit tests for filtered queries and sharing operations. Affected files: - `LLMProviderService`, `LLMModelService`, `ModelSettingsService` and their implementations Acceptance criteria: - GET/list endpoints only return resources the requesting user can access. - Sharing operations work via service/DAO and are covered by tests. Priority / Est.: 2–3 days --- Task 7 — Frontend: Public / Private resource indicators Summary: Add UI indicators (badges) and ownership information so users can see whether a provider/model/settings is public (in "All Users") or private. Action items: 1. Add "Public" badge to `ProviderListItem` when provider is in "All Users" group. 2. Add "Public" badge to `ModelListItem` when model is in "All Users" group. 3. Add "Public" badge to `SettingsListPanel` when settings is in "All Users" group. 4. Display ownership information in detail panels. Affected files/components: - `ProviderListItem`, `ModelListItem`, `SettingsListPanel`, provider/model/settings detail panels. Acceptance criteria: - Public resources visibly show a "Public" badge and ownership info in UI. - Badges update after sharing/unsharing actions. Priority / Est.: 1–2 days --- Task 8 — Frontend: Admin controls for resource sharing Summary: Provide admin UI to make resources public or share with specific groups, with permission checks. Action items: 1. Add "Make Public" button to provider/model/settings detail panels (admin only). 2. Add "Remove Public Access" button to undo. 3. Create "Share with Group" dialog to select group(s) and access mode (read/write). 4. Add permission checks for these operations (e.g. `MANAGE_PUBLIC_RESOURCES`). 5. Wire UI to backend APIs (grant/revoke access endpoints). 6. Add frontend tests (if applicable) and validations. Affected files/components: - provider/model/settings detail panels, share dialog components, admin UI wiring. Acceptance criteria: - Admins can make/unmake resources public. - Admins can share/unshare with groups specifying `AccessMode`. - UI reflects the new sharing status immediately (or after refresh). Priority / Est.: 2–3 days --- Task 9 — Testing & Integration Summary: End-to-end verification of resource sharing, access enforcement, public access semantics, and admin controls. Action items: 1. End-to-end testing of resource sharing paths (owner, shared group, public). 2. Test public resource access (users in "All Users" see public resources). 3. Test private resource access restrictions (users without access cannot see or perform writes). 4. Test admin controls (make public, share with group, revoke). 5. Run performance checks for access checks (JOINs) and optimize queries if needed. 6. Ensure unit/integration test coverage for new DAOs, authorizers, and services. Acceptance criteria: - E2E tests confirm expected behavior for owner, group, public, and denied cases. - No regressions for sessions/groups admin features. Priority / Est.: 2–3 days --- If you'd like I can: - Create this issue now (I'll attach this content) and return the issue URL/number, or - Create a compact checklist version only, or - Start implementing Task 0a and open a PR draft. Created from `temp/Phase 3 Readiness Report.md` (2025-10-06)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Torvian.eu/chatbot#103
No description provided.