diff --git a/AGENTS.md b/AGENTS.md index 9b9221f..6492ef2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,16 +1,18 @@ -# GovOPlaN Issue Reporting Codex Guide +# GovOPlaN Tickets Codex Guide ## Scope -This repository owns the GovOPlaN Issue Reporting platform module seed. +This repository owns the GovOPlaN Tickets domain module seed. -Public or internal problem reporting for broken infrastructure, damaged rooms, IT outages, safety issues, accessibility issues, triage, and routing. +Tickets are queue-oriented reports, requests, incidents, problems, and service +work. Formal administrative procedures remain owned by `govoplan-cases`. ## Boundaries - Depend on kernel contracts from `govoplan-core` and access contracts from `govoplan-access`. - Keep domain behavior in this module; expose integration through manifests, capabilities, API routes, events, typed DTOs, and documentation topics. - Do not import internals from sibling feature modules. Use optional dependencies and capabilities for cross-module behavior. +- Escalation to a case creates a stable cross-module reference; never mutate a ticket into a case or copy a case's authoritative procedural state. - Keep the seed non-invasive until runtime routes, persistence, and WebUI flows are intentionally designed. ## Local Workflow diff --git a/README.md b/README.md index a4840a4..58fade0 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,56 @@ -# GovOPlaN Issue Reporting +# GovOPlaN Tickets **Repository type:** module (domain). -`govoplan-issue-reporting` is the GovOPlaN platform module seed for public or internal problem reporting for broken infrastructure, damaged rooms, IT outages, safety issues, accessibility issues, triage, and routing. +`govoplan-tickets` is the generic GovOPlaN work-intake and service-ticket +module. It covers public and internal reports, requests, incidents, problems, +queues, triage, routing, assignment, service-level state, and auditable +resolution. -Its runtime module ID is `issue_reporting`; the repository and Python distribution retain the hyphenated `govoplan-issue-reporting` name. +Its runtime module ID is `tickets`. This repository is initialized as a discoverable module seed. It exposes a module manifest, initial permissions, role templates, documentation metadata, Gitea workflow templates, and a focused manifest test. It intentionally does not yet add HTTP routes, database models, migrations, or WebUI navigation. ## Initial Ownership -- issue intake -- problem category taxonomy -- triage and routing facts -- public reporter references -- handoff targets +- ticket identity, type, priority, state, and queue +- public and internal intake profiles +- reporter/requester and affected-object references +- triage, routing, assignment, and service-level facts +- resolution evidence and escalation links ## Boundaries -This module does not own: +Tickets are operational work items. They may be resolved entirely within a +queue or linked to a task, project, asset, facility, or formal case. -- internal service desk execution -- legal case handling -- asset lifecycle management +Cases are different: `govoplan-cases` owns the authoritative procedural record +for an administrative matter, including parties, evidence, decisions, +procedural deadlines, and retention. Escalating a ticket creates a stable link; +it does not rewrite the ticket as a case. -Detailed boundary notes are in [docs/ISSUE_REPORTING_DOMAIN_BOUNDARY.md](docs/ISSUE_REPORTING_DOMAIN_BOUNDARY.md). +Detailed boundary notes are in +[docs/TICKETS_DOMAIN_BOUNDARY.md](docs/TICKETS_DOMAIN_BOUNDARY.md). ## Integrations Expected optional integrations: -- helpdesk - cases +- projects +- wiki - assets - facilities - forms_runtime - portal - files - workflow +- tasks +- mail +- notifications +- search ## Development Install @@ -47,23 +58,24 @@ From the core checkout: ```bash cd /mnt/DATA/git/govoplan-core -./.venv/bin/python -m pip install -e ../govoplan-issue-reporting +./.venv/bin/python -m pip install -e ../govoplan-tickets ``` Focused manifest verification: ```bash -cd /mnt/DATA/git/govoplan-issue-reporting +cd /mnt/DATA/git/govoplan-tickets PYTHONPATH=src:/mnt/DATA/git/govoplan-core/src /mnt/DATA/git/govoplan-core/.venv/bin/python -m unittest discover -s tests ``` ## Gitea Workflow -Issue templates are installed under `.gitea/`, and the shared label taxonomy is copied to `docs/gitea-labels.json` with the module label `module/issue-reporting`. +Issue templates are installed under `.gitea/`, and the shared label taxonomy is +copied to `docs/gitea-labels.json` with the module label `module/tickets`. From the core checkout, labels can be synced once a local `GITEA_TOKEN` is available: ```bash cd /mnt/DATA/git/govoplan-core -/mnt/DATA/git/govoplan/tools/gitea/gitea-sync-labels.py --root /mnt/DATA/git/govoplan-issue-reporting --apply +/mnt/DATA/git/govoplan/tools/gitea/gitea-sync-labels.py --root /mnt/DATA/git/govoplan-tickets --apply ``` diff --git a/docs/ISSUE_REPORTING_DOMAIN_BOUNDARY.md b/docs/ISSUE_REPORTING_DOMAIN_BOUNDARY.md deleted file mode 100644 index 68f2371..0000000 --- a/docs/ISSUE_REPORTING_DOMAIN_BOUNDARY.md +++ /dev/null @@ -1,47 +0,0 @@ -# Issue Reporting Domain Boundary - -## Purpose - -Public or internal problem reporting for broken infrastructure, damaged rooms, IT outages, safety issues, accessibility issues, triage, and routing. - -## Owns - -- issue intake -- problem category taxonomy -- triage and routing facts -- public reporter references -- handoff targets - -## Does Not Own - -- internal service desk execution -- legal case handling -- asset lifecycle management - -## Integration Candidates - -- helpdesk -- cases -- assets -- facilities -- forms_runtime -- portal -- files -- workflow - -## Seed State - -The current repository state is intentionally small: - -- module manifest and entry point -- tenant-level permission definitions -- manager and viewer role templates -- documentation topic describing the module boundary -- Gitea issue workflow templates -- manifest contract test - -No runtime API, database model, migration, WebUI route, or navigation item is registered yet. The first implementation slice should preserve the boundary above and only add user-visible surfaces once the workflow model is clear. - -## First Implementation Slice - -Define intake submission, triage status, category, location, evidence, and handoff contracts to helpdesk, cases, assets, or facilities. diff --git a/docs/TICKETS_DOMAIN_BOUNDARY.md b/docs/TICKETS_DOMAIN_BOUNDARY.md new file mode 100644 index 0000000..e9eb19f --- /dev/null +++ b/docs/TICKETS_DOMAIN_BOUNDARY.md @@ -0,0 +1,78 @@ +# Tickets Domain Boundary + +## Purpose + +Queue-oriented operational work: public or internal reports, service requests, +incidents, problems, triage, routing, assignment, service-level tracking, and +auditable resolution. + +## Owns + +- ticket identity, type, category, priority, state, and queue +- public and internal intake profiles +- reporter/requester and affected-object references +- triage, routing, assignment, escalation, and service-level facts +- discussion and resolution evidence references +- stable links to tasks, projects, assets, facilities, and cases + +## Does Not Own + +- formal administrative case identity, parties, evidence, decisions, and retention +- project plans, milestones, and portfolios +- asset lifecycle management +- workflow definitions and task execution + +## Integration Candidates + +- cases +- projects +- wiki +- assets +- facilities +- forms_runtime +- portal +- files +- workflow +- tasks +- mail +- notifications +- search + +## Ticket Versus Case + +A ticket is the operational record of work entering and moving through a queue. +It can be reported with incomplete information, assigned and reassigned, +discussed, resolved, reopened, or linked to another work object. Its lifecycle +answers: what needs attention, who owns the next action, and was it resolved? + +A case is the authoritative procedural record for an administrative matter. It +has formal parties, evidence, decisions, procedural deadlines, access rules, +retention obligations, and a durable case history. Its lifecycle answers: what +matter is being administered, under which procedure, and what formal outcome +was reached? + +Escalation does not convert or duplicate records. It creates an auditable +relation containing the ticket reference, case reference, relation type, +actor, timestamp, and optional handoff note. The ticket remains the intake and +service history; the case becomes authoritative for the formal procedure. + +The former Issue Reporting and Helpdesk concepts become ticket type, intake, +queue, and policy profiles. They do not need separate persistence models. + +## Seed State + +The current repository state is intentionally small: + +- module manifest and entry point +- tenant-level permission definitions +- manager and viewer role templates +- documentation topic describing the module boundary +- Gitea issue workflow templates +- manifest contract test + +No runtime API, database model, migration, WebUI route, or navigation item is registered yet. The first implementation slice should preserve the boundary above and only add user-visible surfaces once the workflow model is clear. + +## First Implementation Slice + +Define ticket identity, intake profiles, queues, triage, assignment, +resolution, and stable escalation links to cases. diff --git a/docs/gitea-labels.json b/docs/gitea-labels.json index 19ac7fa..975c747 100644 --- a/docs/gitea-labels.json +++ b/docs/gitea-labels.json @@ -11,6 +11,12 @@ "description": "New user-visible behavior or platform capability.", "exclusive": true }, + { + "name": "type/user-story", + "color": "1d76db", + "description": "End-to-end user journey or real-world process story used to steer product slices.", + "exclusive": true + }, { "name": "type/task", "color": "1d76db", @@ -143,6 +149,24 @@ "description": "GovOPlaN core runner, shared primitives, shell, or extension points.", "exclusive": false }, + { + "name": "module/dashboard", + "color": "1d76db", + "description": "GovOPlaN Dashboard module behavior or integration.", + "exclusive": false + }, + { + "name": "module/dataflow", + "color": "1d76db", + "description": "GovOPlaN Dataflow module behavior or integration.", + "exclusive": false + }, + { + "name": "module/datasources", + "color": "006b75", + "description": "GovOPlaN governed datasource contracts, catalogs, and integrations.", + "exclusive": false + }, { "name": "module/dms", "color": "c5def5", @@ -151,8 +175,14 @@ }, { "name": "module/docs", - "color": "5319e7", - "description": "GovOPlaN documentation layer behavior or integration.", + "color": "c5def5", + "description": "GovOPlaN Docs module behavior or integration.", + "exclusive": false + }, + { + "name": "module/dist-lists", + "color": "0e8a16", + "description": "GovOPlaN Distribution Lists module behavior or integration.", "exclusive": false }, { @@ -161,6 +191,12 @@ "description": "GovOPlaN Erp module behavior or integration.", "exclusive": false }, + { + "name": "module/evaluation", + "color": "bfdadc", + "description": "GovOPlaN Evaluation module behavior or integration.", + "exclusive": false + }, { "name": "module/files", "color": "006b75", @@ -185,6 +221,12 @@ "description": "GovOPlaN Identity Trust module behavior or integration.", "exclusive": false }, + { + "name": "module/identity", + "color": "bfd4f2", + "description": "GovOPlaN Identity module behavior or integration.", + "exclusive": false + }, { "name": "module/idm", "color": "0052cc", @@ -215,30 +257,66 @@ "description": "GovOPlaN Ops module behavior or integration.", "exclusive": false }, + { + "name": "module/organizations", + "color": "bfdadc", + "description": "GovOPlaN Organizations module behavior or integration.", + "exclusive": false + }, { "name": "module/payments", "color": "bfd4f2", "description": "GovOPlaN Payments module behavior or integration.", "exclusive": false }, + { + "name": "module/permits", + "color": "fbca04", + "description": "GovOPlaN Permits module behavior or integration.", + "exclusive": false + }, { "name": "module/policy", "color": "d93f0b", "description": "GovOPlaN Policy module behavior or integration.", "exclusive": false }, + { + "name": "module/poll", + "color": "e4e669", + "description": "GovOPlaN Poll module behavior or integration.", + "exclusive": false + }, { "name": "module/portal", "color": "1d76db", "description": "GovOPlaN Portal module behavior or integration.", "exclusive": false }, + { + "name": "module/postbox", + "color": "d93f0b", + "description": "GovOPlaN Postbox module behavior or integration.", + "exclusive": false + }, + { + "name": "module/projects", + "color": "5319e7", + "description": "GovOPlaN Projects module behavior or integration.", + "exclusive": false + }, { "name": "module/reporting", "color": "c2e0c6", "description": "GovOPlaN Reporting module behavior or integration.", "exclusive": false }, + { + "name": "module/risk-compliance", + "color": "b60205", + "description": "GovOPlaN Risk Compliance module behavior or integration.", + "exclusive": false + }, { "name": "module/search", "color": "bfdadc", @@ -270,9 +348,21 @@ "exclusive": false }, { - "name": "module/web", - "color": "bfd4f2", - "description": "GovOPlaN public website, product page, or publication content.", + "name": "module/tickets", + "color": "0e8a16", + "description": "GovOPlaN Tickets module behavior or integration.", + "exclusive": false + }, + { + "name": "module/views", + "color": "c5def5", + "description": "GovOPlaN governed task views, interface projections, and workflow view integration.", + "exclusive": false + }, + { + "name": "module/wiki", + "color": "006b75", + "description": "GovOPlaN Wiki module behavior or integration.", "exclusive": false }, { @@ -365,6 +455,12 @@ "description": "Versioning, release locks, tags, packaging, or dependency pins.", "exclusive": false }, + { + "name": "area/security", + "color": "b60205", + "description": "Security posture, static analysis, supply-chain hardening, or vulnerability remediation.", + "exclusive": false + }, { "name": "area/docs", "color": "5319e7", @@ -389,6 +485,48 @@ "description": "Imported from markdown backlog, roadmap, plan, or TODO files.", "exclusive": false }, + { + "name": "source/security-audit", + "color": "d4c5f9", + "description": "Created from a structured security or code-quality audit report.", + "exclusive": false + }, + { + "name": "audit/quick-fix", + "color": "0e8a16", + "description": "Audit finding that appears narrow and directly fixable.", + "exclusive": false + }, + { + "name": "audit/structural", + "color": "d93f0b", + "description": "Audit finding that needs design, refactoring, or behavior review.", + "exclusive": false + }, + { + "name": "audit/complexity", + "color": "fbca04", + "description": "Complexity finding from Radon, Xenon, or equivalent maintainability scans.", + "exclusive": false + }, + { + "name": "audit/duplication", + "color": "c2e0c6", + "description": "Duplicated-code finding from jscpd or equivalent similarity scans.", + "exclusive": false + }, + { + "name": "audit/false-positive", + "color": "cccccc", + "description": "Audit finding reviewed as a narrow false positive or acceptable risk.", + "exclusive": false + }, + { + "name": "audit/needs-design", + "color": "f9d0c4", + "description": "Audit finding that needs an architectural or product decision before implementation.", + "exclusive": false + }, { "name": "codex/ready", "color": "0e8a16", @@ -400,11 +538,5 @@ "color": "f9d0c4", "description": "Needs an explicit human decision before Codex should implement.", "exclusive": false - }, - { - "name": "module/issue-reporting", - "color": "0e8a16", - "description": "GovOPlaN Issue Reporting module behavior or integration.", - "exclusive": false } ] diff --git a/package.json b/package.json index c741a80..1fc76fa 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "@govoplan/issue-reporting", + "name": "@govoplan/tickets", "version": "0.1.8", "private": true, - "description": "GovOPlaN Issue Reporting platform module seed.", + "description": "GovOPlaN Tickets platform module seed.", "type": "module", "peerDependencies": {} } diff --git a/pyproject.toml b/pyproject.toml index a43fc1c..4a22acc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,9 +3,9 @@ requires = ["setuptools>=69", "wheel"] build-backend = "setuptools.build_meta" [project] -name = "govoplan-issue-reporting" +name = "govoplan-tickets" version = "0.1.8" -description = "GovOPlaN Issue Reporting platform module seed." +description = "GovOPlaN Tickets platform module seed." readme = "README.md" requires-python = ">=3.12" license = { file = "LICENSE" } @@ -19,7 +19,7 @@ dependencies = [ where = ["src"] [tool.setuptools.package-data] -govoplan_issue_reporting = ["py.typed"] +govoplan_tickets = ["py.typed"] [project.entry-points."govoplan.modules"] -issue_reporting = "govoplan_issue_reporting.backend.manifest:get_manifest" +tickets = "govoplan_tickets.backend.manifest:get_manifest" diff --git a/src/govoplan_issue_reporting/__init__.py b/src/govoplan_issue_reporting/__init__.py deleted file mode 100644 index a14f8a0..0000000 --- a/src/govoplan_issue_reporting/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""GovOPlaN Issue Reporting module.""" diff --git a/src/govoplan_issue_reporting/backend/__init__.py b/src/govoplan_issue_reporting/backend/__init__.py deleted file mode 100644 index b97ff23..0000000 --- a/src/govoplan_issue_reporting/backend/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Backend integration for the GovOPlaN Issue Reporting module.""" diff --git a/src/govoplan_tickets/__init__.py b/src/govoplan_tickets/__init__.py new file mode 100644 index 0000000..4f3d0d5 --- /dev/null +++ b/src/govoplan_tickets/__init__.py @@ -0,0 +1 @@ +"""GovOPlaN Tickets module.""" diff --git a/src/govoplan_tickets/backend/__init__.py b/src/govoplan_tickets/backend/__init__.py new file mode 100644 index 0000000..23399c6 --- /dev/null +++ b/src/govoplan_tickets/backend/__init__.py @@ -0,0 +1 @@ +"""Backend integration for the GovOPlaN Tickets module.""" diff --git a/src/govoplan_issue_reporting/backend/manifest.py b/src/govoplan_tickets/backend/manifest.py similarity index 56% rename from src/govoplan_issue_reporting/backend/manifest.py rename to src/govoplan_tickets/backend/manifest.py index 747c19c..c36828c 100644 --- a/src/govoplan_issue_reporting/backend/manifest.py +++ b/src/govoplan_tickets/backend/manifest.py @@ -3,21 +3,26 @@ from __future__ import annotations from govoplan_core.core.access import CAPABILITY_AUTH_PERMISSION_EVALUATOR, CAPABILITY_AUTH_PRINCIPAL_RESOLVER from govoplan_core.core.modules import DocumentationLink, DocumentationTopic, ModuleManifest, PermissionDefinition, RoleTemplate -MODULE_ID = "issue_reporting" -MODULE_NAME = "Issue Reporting" +MODULE_ID = "tickets" +MODULE_NAME = "Tickets" MODULE_VERSION = "0.1.8" -READ_SCOPE = "issue_reporting:workspace:read" -WRITE_SCOPE = "issue_reporting:workspace:write" -ADMIN_SCOPE = "issue_reporting:workspace:admin" +READ_SCOPE = "tickets:ticket:read" +WRITE_SCOPE = "tickets:ticket:write" +ADMIN_SCOPE = "tickets:ticket:admin" OPTIONAL_DEPENDENCIES = ( - "helpdesk", "cases", + "projects", + "wiki", "assets", "facilities", "forms_runtime", "portal", "files", "workflow", + "tasks", + "mail", + "notifications", + "search", ) @@ -27,7 +32,7 @@ def _permission(scope: str, label: str, description: str) -> PermissionDefinitio scope=scope, label=label, description=description, - category="Issue Reporting", + category="Tickets", level="tenant", module_id=module_id, resource=resource, @@ -36,22 +41,34 @@ def _permission(scope: str, label: str, description: str) -> PermissionDefinitio PERMISSIONS = ( - _permission(READ_SCOPE, "View issue reporting workspace", "Read issue reporting records, configuration, and workflow context."), - _permission(WRITE_SCOPE, "Manage issue reporting workspace", "Create and update issue reporting records and workflow state."), - _permission(ADMIN_SCOPE, "Administer issue reporting workspace", "Configure issue reporting policies, templates, and tenant-level administration."), + _permission( + READ_SCOPE, + "View tickets", + "Read discoverable tickets, queue state, and resolution context.", + ), + _permission( + WRITE_SCOPE, + "Manage tickets", + "Create, triage, assign, update, resolve, and link tickets.", + ), + _permission( + ADMIN_SCOPE, + "Administer tickets", + "Configure ticket types, queues, service policies, and intake profiles.", + ), ) ROLE_TEMPLATES = ( RoleTemplate( - slug="issue_reporting_manager", - name="Issue Reporting manager", - description="Manage issue reporting records and workflow state.", + slug="tickets_manager", + name="Tickets manager", + description="Triage, assign, update, and resolve tickets.", permissions=(READ_SCOPE, WRITE_SCOPE), ), RoleTemplate( - slug="issue_reporting_viewer", - name="Issue Reporting viewer", - description="Read issue reporting records and workflow context.", + slug="tickets_viewer", + name="Tickets viewer", + description="Read discoverable tickets and their resolution context.", permissions=(READ_SCOPE,), ), ) @@ -60,7 +77,10 @@ DOCUMENTATION = ( DocumentationTopic( id=f"{MODULE_ID}.module-boundary", title=f"{MODULE_NAME} module boundary", - summary="Public or internal problem reporting for broken infrastructure, damaged rooms, IT outages, safety issues, accessibility issues, triage, and routing.", + summary=( + "Queue-oriented reports, requests, incidents, problems, triage, " + "routing, service work, and auditable resolution." + ), body=( "This repository is currently a platform module seed. It registers the domain boundary, " "permission surface, role templates, and documentation metadata before runtime APIs, " @@ -74,14 +94,24 @@ DOCUMENTATION = ( links=( DocumentationLink( label="Repository domain boundary", - href="govoplan-issue-reporting/docs/ISSUE_REPORTING_DOMAIN_BOUNDARY.md", + href="govoplan-tickets/docs/TICKETS_DOMAIN_BOUNDARY.md", kind="repository", ), ), metadata={ "seed": True, - "domain_objects": ['issue intake', 'problem category taxonomy', 'triage and routing facts', 'public reporter references', 'handoff targets'], - "first_slice": "Define intake submission, triage status, category, location, evidence, and handoff contracts to helpdesk, cases, assets, or facilities.", + "domain_objects": [ + "ticket", + "ticket type and queue", + "triage and routing facts", + "reporter and requester references", + "assignment and service-level state", + "resolution and escalation links", + ], + "first_slice": ( + "Define ticket identity, intake profiles, queues, triage, " + "assignment, resolution, and stable escalation links to cases." + ), }, ), ) diff --git a/src/govoplan_issue_reporting/py.typed b/src/govoplan_tickets/py.typed similarity index 100% rename from src/govoplan_issue_reporting/py.typed rename to src/govoplan_tickets/py.typed diff --git a/tests/test_manifest.py b/tests/test_manifest.py index 96bc9df..b7adaab 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -2,18 +2,26 @@ from __future__ import annotations import unittest -from govoplan_issue_reporting.backend.manifest import ADMIN_SCOPE, READ_SCOPE, WRITE_SCOPE, get_manifest +from govoplan_tickets.backend.manifest import ( + ADMIN_SCOPE, + READ_SCOPE, + WRITE_SCOPE, + get_manifest, +) class ManifestSeedTests(unittest.TestCase): def test_manifest_registers_seed_contract(self) -> None: manifest = get_manifest() - self.assertEqual(manifest.id, "issue_reporting") - self.assertEqual(manifest.name, "Issue Reporting") + self.assertEqual(manifest.id, "tickets") + self.assertEqual(manifest.name, "Tickets") self.assertEqual(manifest.dependencies, ("access",)) self.assertEqual({permission.scope for permission in manifest.permissions}, {READ_SCOPE, WRITE_SCOPE, ADMIN_SCOPE}) - self.assertEqual({role.slug for role in manifest.role_templates}, {"issue_reporting_manager", "issue_reporting_viewer"}) + self.assertEqual( + {role.slug for role in manifest.role_templates}, + {"tickets_manager", "tickets_viewer"}, + ) self.assertTrue(manifest.documentation) self.assertIsNone(manifest.route_factory) self.assertIsNone(manifest.migration_spec)