bmc_hub/SAG_MODULE_IMPLEMENTATION_PLAN.md
Christian 29acdf3e01 Add tests for new SAG module endpoints and module deactivation
- Implement test script for new SAG module endpoints BE-003 (Tag State Management) and BE-004 (Bulk Operations).
- Create test cases for creating, updating, and bulk operations on cases and tags.
- Add a test for module deactivation to ensure data integrity is maintained.
- Include setup and teardown for tests to clear database state before and after each test.
2026-01-31 23:16:24 +01:00

32 KiB
Raw Blame History

SAG MODULE IMPLEMENTATION PLAN

Professional Sub-Agent Task Breakdown

Document Version: 2.0
Created: 2026-01-30
Module Location: /app/modules/sag/
API Path: /api/v1/cases
Database Prefix: sag_


EXECUTIVE SUMMARY

The Sag (Case) Module is the process backbone of BMC Hub. It implements a universal entity model where tickets, tasks, and (eventually) orders are all represented as Cases differentiated by:

  • Relations (directional, transitive connections between cases)
  • Tags (workflow state and categorization)
  • Attached modules (billing, hardware, etc.)

This plan provides a phased, task-based approach to complete the implementation with architectural constraints preserved.


1 CURRENT STATE ASSESSMENT

What's Already Implemented

Database Schema (COMPLETE)

  • sag_sager table (cases) - /migrations/001_init.sql

    • Binary status: åben / lukket (constraint enforced)
    • template_key as nullable field (creation-time only)
    • deleted_at for soft-deletes
    • Proper indexes on customer_id, status, ansvarlig_bruger_id
    • Auto-update trigger for updated_at
  • sag_relationer table (relations)

    • Directional: kilde_sag_idmålsag_id
    • relationstype for categorization
    • Soft-delete support
    • Constraint preventing self-relations
  • sag_tags table (tags)

    • tag_navn for categorization
    • state field: open / closed (constraint enforced)
    • closed_at timestamp
    • Soft-delete support
  • sag_kontakter table (case-contact links) - /migrations/002_sag_contacts_relations.sql

    • Many-to-many with roles
  • sag_kunder table (case-customer links)

    • Many-to-many with roles

Backend API (MOSTLY COMPLETE)

Cases CRUD - router.py lines 1-671

  • GET /api/v1/cases - List with filters (status, tag, customer_id, ansvarlig)
  • POST /api/v1/cases - Create case
  • GET /api/v1/cases/{id} - Get case details
  • PATCH /api/v1/cases/{id} - Update case
  • DELETE /api/v1/cases/{id} - Soft-delete

Relations CRUD

  • GET /api/v1/cases/{id}/relations - List relations with titles
  • POST /api/v1/cases/{id}/relations - Create relation
  • DELETE /api/v1/cases/{id}/relations/{relation_id} - Soft-delete

Tags CRUD

  • GET /api/v1/cases/{id}/tags - List tags
  • POST /api/v1/cases/{id}/tags - Add tag (with state support)
  • DELETE /api/v1/cases/{id}/tags/{tag_id} - Soft-delete

Contact/Customer Links

  • POST /api/v1/cases/{id}/contacts - Link contact
  • GET /api/v1/cases/{id}/contacts - List contacts
  • DELETE /api/v1/cases/{id}/contacts/{contact_id} - Remove contact
  • POST /api/v1/cases/{id}/customers - Link customer
  • GET /api/v1/cases/{id}/customers - List customers
  • DELETE /api/v1/cases/{id}/customers/{customer_id} - Remove customer

Search

  • GET /api/v1/search/cases - Full-text search
  • GET /api/v1/search/customers - Customer search
  • GET /api/v1/search/contacts - Contact search

Frontend Views (MOSTLY COMPLETE)

List View - frontend/views.py

  • /cases and /sag routes (dual paths)
  • Filter by status, tag, customer_id
  • Fetches statuses and tags for filters

Detail View

  • /cases/{id} and /sag/{id} routes
  • Shows case, tags, relations, customer
  • Fetches contacts and customers (partially implemented)

Create Form

  • /cases/new and /sag/new routes
  • Template exists (create.html)

Edit Form - Template exists (edit.html) but no backend route

Templates (COMPLETE)

All four templates exist:

  • index.html - Case list with Nordic Top design, filters, dark mode
  • detail.html - Case details with relations, tags, info sections
  • create.html - Create form with customer search, validation
  • edit.html - Edit form (needs backend route)

🔴 Architectural Violations Found

VIOLATION 1: Duplicate API Paths

Issue: Router has both /sag/* and /cases/* endpoints doing identical things.

  • Lines 14-157: /sag prefix endpoints
  • Lines 327-671: /cases prefix endpoints (duplicates)

Fix Required: Remove /sag/* endpoints, keep only /cases/* (architectural standard).

VIOLATION 2: Missing Tag State Management

Issue: Tag closing endpoint missing.

  • PATCH /api/v1/cases/{id}/tags/{tag_id} should allow closing tags (set state='closed', closed_at=NOW())
  • Currently only delete (soft) exists

Fix Required: Add tag state update endpoint.

VIOLATION 3: Missing Edit Route

Issue: edit.html template exists but no backend route to serve it.

Fix Required: Add GET /cases/{id}/edit view route.

⚠️ What Needs Enhancement

  1. Tag State Workflow - Endpoint to close tags (not delete)
  2. Edit View Route - Backend route for edit form
  3. Relation Type Validation - Should validate allowed relation types
  4. Bulk Operations - Close multiple tags, archive cases
  5. Activity Log - Track who changed what (future phase)
  6. Order Integration - Link cases to orders (future phase)

2 PHASE OVERVIEW

Phase 1: Database Schema Validation (30 min)

  • Verify all tables match architectural constraints
  • Add any missing indexes
  • Validate soft-delete coverage

Phase 2: Backend API Enhancement (2-3 hours)

  • Remove duplicate /sag/* endpoints
  • Add tag state management endpoint
  • Add edit view route
  • Improve error handling
  • Add relation type validation

Phase 3: Frontend Enhancement (2-3 hours)

  • Wire up edit form
  • Add tag closing UI
  • Improve relation visualization
  • Add bulk operations UI
  • Enhance mobile responsiveness

Phase 4: Order Integration Planning (1 hour)

  • Define order-case relation types
  • Document order creation workflow
  • Plan order table schema
  • Define API contract

Phase 5: Documentation (1 hour)

  • Update module README
  • Create API documentation
  • Document relation types
  • Create workflow examples

Phase 6: QA & Testing (1-2 hours)

  • Unit tests for CRUD operations
  • Integration tests for relations
  • Frontend E2E tests
  • Soft-delete verification
  • Module disable/enable test

Total Estimate: 8-12 hours


3 SUB-AGENT TASK BREAKDOWN


PHASE 1: DATABASE SCHEMA VALIDATION

DB-001: Schema Compliance Audit

Assigned: DB-Agent
Estimated Time: 30 minutes
Dependencies: None

Description: Audit all sag_* tables against architectural constraints. Verify:

  • Binary status constraint on sag_sager
  • Tag state constraint on sag_tags
  • Soft-delete columns present
  • No missing indexes
  • Trigger functions working

Inputs:

  • /migrations/001_init.sql
  • /migrations/002_sag_contacts_relations.sql
  • Database connection

Outputs:

  • Validation report (pass/fail for each constraint)
  • SQL script for any missing indexes/constraints

Done Criteria:

  • All constraints match architectural rules
  • All soft-delete columns present
  • All indexes exist and performant

PHASE 2: BACKEND API ENHANCEMENT

BE-001: Remove Duplicate /sag/* Endpoints

Assigned: Backend-Agent
Estimated Time: 45 minutes
Dependencies: None

Description: Remove duplicate endpoints with /sag prefix (lines 14-330). Keep only /cases prefix endpoints. Update any internal references.

Inputs:

  • /app/modules/sag/backend/router.py

Outputs:

  • Modified router.py with only /cases endpoints
  • Updated imports if needed

Done Criteria:

  • No /sag prefix endpoints remain
  • All functionality preserved under /cases
  • No broken internal references

BE-002: Add Tag State Management Endpoint

Assigned: Backend-Agent
Estimated Time: 45 minutes
Dependencies: BE-001

Description: Add PATCH /api/v1/cases/{id}/tags/{tag_id} endpoint to close tags without deleting. Should:

  • Accept {"state": "closed"} payload
  • Set closed_at = NOW()
  • NOT set deleted_at (tags are closed, not deleted)
  • Return updated tag

Inputs:

  • /app/modules/sag/backend/router.py
  • sag_tags table schema

Outputs:

  • New endpoint in router.py
  • Proper error handling

Done Criteria:

  • Endpoint closes tag (state='closed', closed_at set)
  • Returns 404 if tag not found
  • Doesn't soft-delete
  • Logs action with emoji prefix

BE-003: Add Edit View Route

Assigned: Backend-Agent
Estimated Time: 30 minutes
Dependencies: BE-001

Description: Add GET /cases/{id}/edit route in frontend/views.py to serve the edit form. Should fetch case and render edit.html template.

Inputs:

  • /app/modules/sag/frontend/views.py
  • /app/modules/sag/templates/edit.html

Outputs:

  • New route in views.py
  • Template receives case data

Done Criteria:

  • Route returns edit form
  • Form pre-populated with case data
  • Returns 404 if case not found

BE-004: Add Relation Type Validation

Assigned: Backend-Agent
Estimated Time: 45 minutes
Dependencies: BE-001

Description: Add validation for allowed relation types when creating relations. Define allowed types:

  • derived (spawned from)
  • blocks (prevents progress)
  • executes (performs work for)
  • relates_to (generic link)

Reject other types with 400 error.

Inputs:

  • /app/modules/sag/backend/router.py (relation creation endpoint)

Outputs:

  • Updated POST /api/v1/cases/{id}/relations with validation
  • Error message listing allowed types

Done Criteria:

  • Only allowed types accepted
  • 400 error with clear message for invalid types
  • Logged validation failures

BE-005: Improve Error Handling

Assigned: Backend-Agent
Estimated Time: 45 minutes
Dependencies: BE-001, BE-002, BE-003, BE-004

Description: Standardize error responses across all endpoints:

  • Use consistent HTTPException format
  • Include helpful error messages
  • Log all errors with context
  • Return proper status codes

Inputs:

  • All endpoint functions in router.py and views.py

Outputs:

  • Consistent error handling pattern
  • Improved logging

Done Criteria:

  • All errors return proper status codes
  • Error messages are user-friendly
  • All errors logged with context
  • No uncaught exceptions

PHASE 3: FRONTEND ENHANCEMENT

FE-001: Wire Up Edit Form Backend Connection

Assigned: Frontend-Agent
Estimated Time: 45 minutes
Dependencies: BE-003

Description: Complete the edit form JavaScript to:

  • Load case data into form
  • Submit to PATCH /api/v1/cases/{id}
  • Handle success/error responses
  • Redirect to detail view on success

Inputs:

  • /app/modules/sag/templates/edit.html
  • Backend edit route
  • PATCH endpoint

Outputs:

  • Functional edit form with submission
  • Success/error feedback
  • Redirect on success

Done Criteria:

  • Form loads case data
  • Submission calls PATCH endpoint
  • Success redirects to /cases/{id}
  • Errors displayed to user

FE-002: Add Tag Closing UI

Assigned: Frontend-Agent
Estimated Time: 60 minutes
Dependencies: BE-002

Description: Add UI to close tags (not delete) in detail view:

  • Add "Close Tag" button next to each open tag
  • Call PATCH /api/v1/cases/{id}/tags/{tag_id} with state='closed'
  • Update UI to show closed state (greyed out, strikethrough)
  • Keep closed tags visible in UI

Inputs:

  • /app/modules/sag/templates/detail.html
  • Tag closing endpoint

Outputs:

  • Close button on each open tag
  • Visual distinction for closed tags
  • AJAX call to close endpoint

Done Criteria:

  • Closed tags remain visible
  • Visual feedback on state change
  • No page reload needed
  • Error handling for failures

FE-003: Improve Relation Visualization

Assigned: Frontend-Agent
Estimated Time: 90 minutes
Dependencies: None

Description: Enhance relation display in detail view:

  • Group relations by type (derived, blocks, executes, relates_to)
  • Show directionality clearly (this case → target vs. source → this case)
  • Add visual indicators (arrows, colors)
  • Make relation targets clickable links

Inputs:

  • /app/modules/sag/templates/detail.html
  • Relation data from backend

Outputs:

  • Updated relation section with grouping
  • Visual indicators for direction
  • Clickable links to related cases

Done Criteria:

  • Relations grouped by type
  • Direction clear (outgoing vs incoming)
  • All targets are clickable
  • Mobile-responsive

FE-004: Add Bulk Operations UI

Assigned: Frontend-Agent
Estimated Time: 90 minutes
Dependencies: BE-002

Description: Add bulk operations to list view:

  • Checkboxes to select multiple cases
  • "Close Selected" button (set status='lukket')
  • "Archive Selected" button (soft-delete)
  • Confirmation dialogs

Inputs:

  • /app/modules/sag/templates/index.html
  • Update/delete endpoints

Outputs:

  • Selection UI in list view
  • Bulk action buttons
  • Confirmation dialogs

Done Criteria:

  • Multiple cases selectable
  • Bulk close works
  • Bulk archive works (soft-delete)
  • Confirmation required
  • Success feedback shown

FE-005: Enhance Mobile Responsiveness

Assigned: Frontend-Agent
Estimated Time: 60 minutes
Dependencies: FE-001, FE-002, FE-003, FE-004

Description: Ensure all views work on mobile:

  • Stack filters vertically on small screens
  • Make tables scrollable or card-based
  • Touch-friendly buttons (min 44px)
  • Collapsible sections for detail view

Inputs:

  • All template files

Outputs:

  • Updated CSS with media queries
  • Mobile-optimized layouts

Done Criteria:

  • All views usable on 375px width
  • No horizontal scroll needed
  • Touch targets large enough
  • Text readable without zoom

PHASE 4: ORDER INTEGRATION PLANNING

INT-001: Define Order-Case Relation Model

Assigned: Integration-Agent
Estimated Time: 30 minutes
Dependencies: None

Description: Document how orders integrate with cases:

  • Orders CAN be created independently
  • Orders MUST be linkable to one or more cases
  • When order created from case → create relation
  • Define relation type for order links (e.g., fulfills, invoices_for)

Inputs:

  • Architectural constraints document
  • Current relation types

Outputs:

  • Design document: docs/ORDER_CASE_INTEGRATION.md
  • Relation type definitions
  • Workflow diagrams

Done Criteria:

  • Clear definition of order independence
  • Relation type defined
  • Creation workflow documented
  • No violation of "orders are not cases" rule

INT-002: Plan Order Table Schema

Assigned: Integration-Agent
Estimated Time: 45 minutes
Dependencies: INT-001

Description: Design order tables with case linking:

  • orders table (id, title, description, status, etc.)
  • order_case_relations table (order_id, case_id, relation_type)
  • NO embedding of case logic in orders
  • Soft-delete everywhere

Inputs:

  • Order-case relation model (INT-001)
  • Existing sag_* schema

Outputs:

  • SQL migration draft: migrations/XXX_orders.sql
  • Schema documentation

Done Criteria:

  • Order table defined
  • Many-to-many relation to cases
  • No parent/child embedding
  • Soft-delete columns present

INT-003: Define Order API Contract

Assigned: Integration-Agent
Estimated Time: 45 minutes
Dependencies: INT-002

Description: Define order API endpoints:

  • GET /api/v1/orders - List orders
  • POST /api/v1/orders - Create order (optionally from case)
  • POST /api/v1/orders/{id}/cases - Link to case
  • GET /api/v1/cases/{id}/orders - Get orders for case

Inputs:

  • Order schema (INT-002)
  • Case API patterns

Outputs:

  • API specification document
  • Example requests/responses

Done Criteria:

  • All CRUD operations defined
  • Case linking endpoints defined
  • Consistent with case API patterns
  • Examples provided

PHASE 5: DOCUMENTATION

DOC-001: Update Module README

Assigned: Docs-Agent
Estimated Time: 30 minutes
Dependencies: BE-001 through BE-005

Description: Update /app/modules/sag/README.md with:

  • Current implementation status
  • All API endpoints with examples
  • Relation types and meanings
  • Tag workflow explanation
  • Architectural constraints summary

Inputs:

  • Current implementation
  • Backend router
  • Templates

Outputs:

  • Updated README.md

Done Criteria:

  • All endpoints documented
  • Examples provided
  • Architectural rules explained
  • Easy to understand for new developers

DOC-002: Create API Documentation

Assigned: Docs-Agent
Estimated Time: 45 minutes
Dependencies: BE-001 through BE-005

Description: Create OpenAPI-style documentation for all endpoints:

  • Request/response schemas
  • Status codes
  • Error responses
  • Example curl commands

Inputs:

  • Backend router
  • Pydantic models (if any)

Outputs:

  • docs/SAG_API_REFERENCE.md

Done Criteria:

  • All endpoints documented
  • Schemas defined
  • Examples provided
  • Status codes listed

DOC-003: Document Relation Types

Assigned: Docs-Agent
Estimated Time: 30 minutes
Dependencies: BE-004

Description: Create reference guide for relation types:

  • derived - Target case spawned from source
  • blocks - Source blocks target from progressing
  • executes - Target performs work for source
  • relates_to - Generic association

Include use cases and examples.

Inputs:

  • Relation type validation (BE-004)
  • Existing use patterns

Outputs:

  • docs/CASE_RELATION_TYPES.md

Done Criteria:

  • All types explained
  • Use cases provided
  • Examples given
  • Directionality clear

DOC-004: Create Workflow Examples

Assigned: Docs-Agent
Estimated Time: 45 minutes
Dependencies: DOC-001, DOC-002, DOC-003

Description: Document common workflows:

  1. Customer calls → create support case → derive hardware order case → execute fulfillment case
  2. Billing cycle → create invoice case → relate to completed support cases
  3. Project → create project case → derive task cases → track via tags

Inputs:

  • All documentation
  • Current implementation

Outputs:

  • docs/SAG_WORKFLOWS.md

Done Criteria:

  • At least 3 workflows documented
  • Step-by-step instructions
  • API calls shown
  • Relation chains visualized

PHASE 6: QA & TESTING

QA-001: Backend CRUD Tests

Assigned: QA-Agent
Estimated Time: 90 minutes
Dependencies: BE-001 through BE-005

Description: Write integration tests for all CRUD operations:

  • Create case
  • Read case
  • Update case
  • Delete case (soft)
  • Verify deleted_at set correctly

Inputs:

  • Backend router
  • Test database

Outputs:

  • Test file: tests/test_sag_crud.py
  • At least 20 test cases

Done Criteria:

  • All CRUD operations tested
  • Soft-delete verified
  • Error cases tested
  • All tests pass

QA-002: Relation Tests

Assigned: QA-Agent
Estimated Time: 60 minutes
Dependencies: BE-001, BE-004

Description: Test relation operations:

  • Create relation between cases
  • List relations (both directions)
  • Validate relation type validation
  • Delete relation (soft)
  • Prevent self-relations

Inputs:

  • Relation endpoints
  • Test database

Outputs:

  • Test file: tests/test_sag_relations.py
  • At least 10 test cases

Done Criteria:

  • Create/delete tested
  • Type validation tested
  • Self-relation prevention tested
  • Directionality correct

QA-003: Tag Workflow Tests

Assigned: QA-Agent
Estimated Time: 60 minutes
Dependencies: BE-002

Description: Test tag lifecycle:

  • Add tag to case
  • Close tag (state='closed', closed_at set)
  • Verify closed tags not deleted
  • Delete tag (soft)
  • List tags (filter by state)

Inputs:

  • Tag endpoints
  • Test database

Outputs:

  • Test file: tests/test_sag_tags.py
  • At least 8 test cases

Done Criteria:

  • Add/close/delete tested
  • State transitions verified
  • Soft-delete vs close distinction tested
  • All tests pass

QA-004: Frontend E2E Tests

Assigned: QA-Agent
Estimated Time: 90 minutes
Dependencies: FE-001 through FE-005

Description: Test frontend user flows:

  • Navigate to case list
  • Filter by status/tag
  • Create new case
  • View case details
  • Edit case
  • Add/close tag
  • Add relation
  • Delete case

Inputs:

  • All frontend templates
  • Browser automation tool (Playwright/Selenium)

Outputs:

  • Test file: tests/test_sag_frontend.py
  • At least 10 E2E scenarios

Done Criteria:

  • All major flows tested
  • Form submissions work
  • Navigation works
  • Error handling tested

QA-005: Module Disable/Enable Test

Assigned: QA-Agent
Estimated Time: 30 minutes
Dependencies: QA-001, QA-002, QA-003, QA-004

Description: Test module deactivation:

  1. Create test cases/relations/tags
  2. Disable module (enabled=false in module.json)
  3. Verify endpoints return 404
  4. Verify database data intact
  5. Re-enable module
  6. Verify data still accessible

Inputs:

  • Module loader
  • Test database

Outputs:

  • Test file: tests/test_sag_module_lifecycle.py

Done Criteria:

  • Disable prevents access
  • Data preserved
  • Re-enable restores access
  • No data loss

4 DEPENDENCY GRAPH

Sequential Dependencies (Critical Path)

DB-001 (30m)
  ↓
BE-001 (45m)  ← MUST complete before any backend work
  ↓
  ├→ BE-002 (45m)
  ├→ BE-003 (30m)
  ├→ BE-004 (45m)
  └→ BE-005 (45m)  ← Touches all other BE tasks
       ↓
  ┌────┴────┐
  ↓         ↓
FE-001   QA-001 (90m)
(45m)       ↓
  ↓      QA-002 (60m)
FE-002     ↓
(60m)   QA-003 (60m)
  ↓         ↓
FE-003   QA-004 (90m)
(90m)       ↓
  ↓      QA-005 (30m)
FE-004
(90m)
  ↓
FE-005
(60m)

Parallel Opportunities

Wave 1 (after BE-001):

  • BE-002, BE-003, BE-004 can run in parallel
  • Saves ~90 minutes

Wave 2 (after BE-005):

  • FE-001, FE-003, QA-001, QA-002 can run in parallel
  • DOC-001, DOC-002, DOC-003 can run in parallel
  • Saves ~2 hours

Wave 3 (after FE-004):

  • FE-005, QA-004, DOC-004 can run in parallel
  • Saves ~1 hour

Wave 4 (order integration):

  • INT-001, INT-002, INT-003 can run in parallel (independent of other work)

Critical Path Time

If executed sequentially: ~12 hours
If parallelized optimally: ~6-7 hours

Where Orders Integrate

Order Integration is PARALLEL to Case Enhancement:

  • INT-001, INT-002, INT-003 can start immediately
  • Do NOT block case module completion
  • Orders gain meaning when linked to cases via relations
  • No architectural changes to cases needed

Order-Case Interface:

Cases Module (Complete)
    ↓
Orders Module (New)
    ↓
order_case_relations table
    ↓
Relation type: "fulfills" / "invoices_for"

5 VALIDATION CHECKLIST

Phase 1: Database Schema

  • Binary status constraint verified (åben / lukket)
  • Tag state constraint verified (open / closed)
  • All soft-delete columns present
  • All indexes exist and performant
  • Triggers working (updated_at auto-update)
  • No foreign key errors
  • Relation self-reference prevented

Phase 2: Backend API

  • No duplicate /sag/* endpoints exist
  • Only /cases prefix used
  • Tag closing endpoint works (PATCH tags/{id})
  • Edit view route serves form
  • Relation type validation enforces allowed types
  • All endpoints return consistent error format
  • All errors logged with context
  • Soft-deletes set deleted_at, not physical delete

Phase 3: Frontend

  • Edit form loads case data
  • Edit form submits to PATCH endpoint
  • Tag closing UI doesn't delete tags
  • Closed tags remain visible (greyed out)
  • Relations grouped by type
  • Directionality clear (in/out)
  • Bulk operations work
  • All views mobile-responsive (375px)

Phase 4: Order Integration

  • Order-case relation model documented
  • Orders can be created independently
  • Orders linkable to multiple cases
  • No case logic embedded in orders
  • Order table schema has soft-deletes
  • API contract consistent with case API

Phase 5: Documentation

  • README updated with current state
  • All endpoints documented
  • Relation types explained
  • Workflows documented
  • Examples provided

Phase 6: Testing

  • All CRUD operations tested
  • Relation creation/deletion tested
  • Tag state transitions tested
  • Frontend flows tested
  • Module disable/enable tested
  • Data preserved after disable
  • All tests pass

ARCHITECTURAL CONSTRAINT RE-VALIDATION

After each phase, validate these rules:

Core Entity Rule

  • Only one entity: Case
  • Tickets/tasks are cases with different tags/relations
  • ⚠️ Orders are transactional objects, NOT cases (separate table)

Orders Exception

  • ⚠️ Orders can be created independently (INT-002)
  • ⚠️ Orders linkable to cases via relations (INT-002)
  • ⚠️ No case logic in order workflow (INT-001)

Template Usage

  • template_key only used at creation
  • No business logic depends on it

Case Status

  • Binary only: åben / lukket
  • Workflow state via tags

Tags

  • Represent work to be done
  • Have state: open / closed
  • Never deleted when completed (closed instead)
  • Closing = completion of responsibility

Relations

  • First-class data (own table)
  • Directional (kilde → mål)
  • Transitive (chains allowed)
  • No parent/child duality in stored data
  • UI derives parent/child views

Deletion Policy

  • All deletes are soft-deletes
  • deleted_at mandatory everywhere

Modeling Rule

  • If you think you need a new table → use relations instead
  • ⚠️ Exception: Orders (per architectural rule)

TEST SCENARIOS BY PHASE

Phase 1: Database

  1. Insert case with status='other' → constraint violation
  2. Insert tag with state='pending' → constraint violation
  3. Create relation with kilde_sag_id = målsag_id → constraint violation
  4. Soft-delete case → deleted_at set, not physical delete
  5. Query cases WHERE deleted_at IS NULL → deleted cases excluded

Phase 2: Backend

  1. Call /sag/cases → 404 (removed endpoint)
  2. Call /cases → 200 with case list
  3. PATCH tag state to 'closed' → closed_at set, deleted_at NULL
  4. DELETE tag → deleted_at set, state unchanged
  5. POST relation with type='invalid' → 400 error
  6. POST relation with type='derived' → 201 created

Phase 3: Frontend

  1. Edit case form → loads current values
  2. Submit edit form → case updated, redirect to detail
  3. Click "Close Tag" → tag state='closed', remains visible, greyed
  4. Add relation → dropdown shows allowed types
  5. Bulk close cases → all selected closed
  6. View on 375px screen → no horizontal scroll

Phase 4: Order Integration

  1. Create order without case → success
  2. Link order to case → relation created
  3. View case → shows linked orders
  4. View order → shows linked cases
  5. Delete case → order remains (independent)

Phase 5: Documentation

  1. Developer reads README → understands architecture
  2. Developer reads API docs → can call endpoints
  3. Developer reads relation types → understands usage
  4. Developer reads workflows → can implement feature

Phase 6: QA

  1. All CRUD operations → success
  2. Soft-delete case → data preserved
  3. Module disabled → endpoints return 404
  4. Module re-enabled → data accessible again
  5. Tag closed → not deleted
  6. Relation created → directionality correct

ANTI-PATTERNS TO AVOID

DO NOT:

  • Create tickets or tasks tables (use cases with tags)
  • Embed workflow logic in orders
  • Introduce parent/child trees outside relations
  • Add state machines (use tags)
  • Optimize prematurely (no Redis, no caching yet)
  • Physical delete anything (always soft-delete)
  • Skip validation (enforce constraints)
  • Duplicate endpoints (one path per resource)

DO:

  • Use relations to express connections
  • Use tags to express workflow state
  • Keep orders independent but relatable
  • Soft-delete everything
  • Log all actions with emoji prefixes
  • Return user-friendly errors
  • Preserve data on module disable

ROLLOUT PLAN

Development Environment

  1. Complete Phases 1-3 in dev
  2. Test with test data
  3. Verify module disable/enable

Staging/QA

  1. Run full QA suite (Phase 6)
  2. Performance test with 10k+ cases
  3. Load test endpoints
  4. Verify soft-deletes work at scale

Production

  1. Run schema validation (DB-001)
  2. Deploy backend changes (Phase 2)
  3. Deploy frontend changes (Phase 3)
  4. Monitor logs for errors
  5. Verify no downtime
  6. Roll back if issues (soft-deletes preserve data)

Post-Deployment

  1. Monitor case creation rate
  2. Track relation usage patterns
  3. Identify most-used tags
  4. Plan order integration (Phase 4)

SUCCESS CRITERIA

The Sag Module implementation is COMPLETE when:

Database

  • All constraints enforced
  • Soft-deletes everywhere
  • Indexes performant

Backend

  • No duplicate endpoints
  • Tag closing works
  • Relations validated
  • Edit route exists
  • Errors consistent

Frontend

  • Edit form works
  • Tag closing UI works
  • Relations visualized
  • Bulk operations work
  • Mobile responsive

Order Integration

  • Model documented
  • Schema planned
  • API defined
  • No constraint violations

Documentation

  • README complete
  • API documented
  • Relation types explained
  • Workflows documented

Testing

  • All CRUD tested
  • Relations tested
  • Tags tested
  • Frontend tested
  • Module lifecycle tested

Architectural Compliance

  • One entity: Case
  • Orders separate but linkable
  • Template key not used in logic
  • Status binary
  • Tags never deleted (closed)
  • Relations directional
  • Soft-deletes everywhere
  • No new tables (except orders)

APPENDIX A: TASK TIME SUMMARY

Phase Task Count Sequential Time Parallel Time
Phase 1: Database 1 30m 30m
Phase 2: Backend 5 3h 30m 1h 45m
Phase 3: Frontend 5 5h 45m 2h 30m
Phase 4: Orders 3 2h 30m (parallel)
Phase 5: Docs 4 2h 30m 45m (parallel)
Phase 6: QA 5 4h 30m 2h
TOTAL 23 18h 45m ~8h

APPENDIX B: RELATION TYPE REFERENCE

Type Direction Meaning Example
derived A → B B spawned from A Support call → hardware order
blocks A → B A prevents B Missing part → installation task
executes A → B A performs work for B Packing task → customer order
relates_to A ↔ B Generic association Related support tickets

Validation: Only these four types allowed in POST /api/v1/cases/{id}/relations


APPENDIX C: TAG STATE LIFECYCLE

Tag Created (state='open', closed_at=NULL)
    ↓
[Work happens]
    ↓
Tag Closed (state='closed', closed_at=NOW(), deleted_at=NULL)
    ↓
Tag Remains Visible (greyed out in UI)
    ↓
[Optional: Technical cleanup]
    ↓
Tag Soft-Deleted (deleted_at=NOW())

Key Rule: Closing ≠ Deleting. Tags are closed when work is done, deleted only if added by mistake.


APPENDIX D: ORDER-CASE INTEGRATION EXAMPLE

Scenario: Customer needs new laptop

1. Support Call (Case ID: 1001)
   - Type: Case
   - Tags: [support, hardware]
   - Status: åben

2. Create Hardware Order (Order ID: 5001)
   - Type: Order (separate table)
   - Items: [Laptop, Charger]
   - Status: pending

3. Link Order to Case
   - POST /api/v1/orders/5001/cases
   - Body: {"case_id": 1001, "relation_type": "fulfills"}
   - Creates entry in order_case_relations

4. Fulfillment Task (Case ID: 1002)
   - Type: Case
   - Tags: [fulfillment]
   - Status: åben
   - Relation: 1002 executes 1001

5. Query Cases for Order
   - GET /api/v1/orders/5001/cases
   - Returns: [Case 1001]

6. Query Orders for Case
   - GET /api/v1/cases/1001/orders
   - Returns: [Order 5001]

Architecture Preserved:

  • Order is NOT a case
  • Order is independent (can exist without case)
  • Order gains context through case relation
  • Cases remain the process backbone

DOCUMENT CONTROL

Version History:

Version Date Author Changes
1.0 2026-01-30 GitHub Copilot Initial plan
2.0 2026-01-30 GitHub Copilot Sub-agent task breakdown added

Approval:

  • Architect Review
  • Technical Lead Review
  • Project Manager Approval

Next Review Date: After Phase 2 completion


END OF IMPLEMENTATION PLAN