feat(tickets): attach the procedure KB article to a ticket #495
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/PMS-730-ticket-procedure-kb-article"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Groundwork for PMS-730 (client request forms / MACD): attach the KB article that describes HOW to perform the work a ticket asks for, so whoever picks the ticket up has the procedure in hand.
Corrects a wrong premise in the issue
PMS-730's background says "There is no ticket-to-article link anywhere in the schema". That is wrong:
tickets.source_kb_article_idhas existed since migration 068 (PMS-452), is bound on the ticket create path, and feeds the PMS-485 "top ticket-driving articles" widget. So this PR adds a SECOND link rather than a first, and the interesting question became whether to reuse the existing one.Why a separate column rather than reusing
source_kb_article_idThe two links point in opposite directions.
source_kb_article_idrecords the article a ticket was opened FROM: the SPA offers "Open ticket about this article", stamps the column, andKnowledgeBaseService::list_top_ticket_driving_articlescounts those stamps to answer "which articles drive the most tickets", i.e. where the docs are FAILING the user. A procedure link is the reverse: the ticket needs the article. Stamping the same column would fold every MACD request into that count and invert its meaning, reporting a working runbook as a documentation failure. Migration 099 carries the full rationale inline, and the new test pins the exclusion so a future refactor cannot quietly merge the two.What is here
migrations/099_tickets_procedure_kb_article.sql:tickets.procedure_kb_article_id, FK tokb_articleswithON DELETE SET NULL(mirrors 068: retiring an article drops the linkage, not the ticket), plus a partial index on(tenant_id, procedure_kb_article_id)sized for PMS-732's "tracked time by request type, surfaced on the article" aggregation. No RLS work: a policy attaches per table, not per column, andticketsalready carries the fail-closedtenant_isolationpolicy.CreateTicketRequestaccepts the field, defaulting toNone, so the agent, portal, RMM and email-intake create paths are untouched. The create INSERT binds it.TicketandTicketResponsereturn it.TicketResponsealso carries a JOINedprocedure_kb_article_title, following the PMS-344asset_id/asset_nameshape, so the ticket detail can render the procedure link without a second fetch.tests/knowledge_base.rsgains a test covering the round trip through create and get with the title resolved, the widget exclusion described above, and theON DELETE SET NULLbehaviour.Deliberately not here
The change-type to article mapping that PMS-730 also implies. Its left-hand side is the request-type vocabulary that PMS-731's form definitions will own, so a standalone mapping table now would create a second vocabulary that PMS-731 then duplicates. It collapses naturally to a
kb_article_idcolumn on the form definition row and belongs in that issue.Verification
cargo fmt --all --check,cargo clippy --all-targets -- -D warnings, and the fullcargo test --testssuite (714 passed, 0 failed, 71 test binaries) all green locally, pluscheck-migration-prefixes.nu,check-migration-immutability.nuandcheck-pool-safety.nu.Note for anyone running the suite locally:
just test-integrationcurrently fails with42501 permission denied to create databaseagainst a compose stack that has provisioned its roles, becausesrc/db/provision.rscreatesmokosh_migratorwithLOGIN BYPASSRLSand noCREATEDBwhile#[sqlx::test]creates a database per test. CI is unaffected becauseintegration.ymlpointsDATABASE_URLat thepostgressuperuser. I ran with the superuser URL to match CI; the recipe divergence is worth its own fix and is not addressed here.