• v0.2.0 9d641d56ed

    v0.2.0
    Some checks failed
    Build OCI container / Build and push mokosh-api image (push) Failing after 9s
    Stable

    David released this 2026-05-14 23:57:18 +02:00 | 1257 commits to main since this release

    Changelog

    da5b705 Merge pull request 'Release v0.2.0' (#228) from release/v0.2.0 into main
    cbc6b03 Release v0.2.0
    00084a0 Merge pull request 'fix(assets): wire configured AES key and harden vault crypto integrity' (#226) from fix/pms-188-assets-zero-key-crypto-integrity into main
    93df0f9 Merge origin/main into fix/pms-188-assets-zero-key-crypto-integrity
    92a4975 Merge origin/main into fix/pms-188-assets-zero-key-crypto-integrity
    3a4327a Merge pull request 'feat(rls): activate RLS at runtime via split migrator/app DB roles' (#224) from feat/pms-285-rls-runtime-role-split into main
    714658e Merge origin/main into feat/pms-285-rls-runtime-role-split
    55000e0 Merge pull request 'chore(cleanup): remove dead crates code and stray config/seed/test cruft' (#220) from chore/pms-202-remove-dead-code into main
    1f4884e Merge origin/main into chore/pms-202-remove-dead-code
    e1e04e2 Merge pull request 'chore(cleanup): remove dead and stray code from src/ tree' (#218) from chore/pms-201-remove-dead-stray-code into main
    5755852 Merge origin/main into chore/pms-201-remove-dead-stray-code
    69bdf0a Merge pull request 'fix: correct rmm, notifications, SLA, KB, portal, and contacts defects' (#217) from fix/pms-195-module-correctness-defects into main
    0c7f45d Merge origin/main into fix/pms-195-module-correctness-defects
    02c6300 Merge pull request 'test(settings): hit canonical /api/v1/invoices in module-gate tests' (#215) from chore/checks-workflow-986a08ef into main
    258450c Merge origin/main into chore/checks-workflow-986a08ef
    2e34ede Merge pull request 'fix(contracts,billing): close financial-integrity gaps' (#213) from fix/pms-194-contracts-billing-financial-integrity into main
    6d07954 Merge origin/main into fix/pms-194-contracts-billing-financial-integrity
    bad33e0 Merge pull request 'refactor: consolidate duplicated helpers, types, and test fixtures' (#212) from feat/pms-199-consolidate-duplicated-helpers into main
    c00cae2 Merge origin/main into feat/pms-199-consolidate-duplicated-helpers
    eac8dbb Merge pull request 'fix(db): converge ticket filter builder; audit count_query placeholder family' (#211) from feat/pms-197-audit-count-query-placeholder-family into main
    4a7c72e Merge origin/main into feat/pms-197-audit-count-query-placeholder-family
    06bddef Merge pull request 'fix(schema): harden migrations, FKs, seed, and truncation (PMS-196)' (#210) from feat/pms-196-harden-migrations-rls-integrity into main
    ad47e38 Merge origin/main into feat/pms-196-harden-migrations-rls-integrity
    85fd769 Merge pull request 'fix(tickets): scope writes to tenant and validate FK references' (#209) from fix/pms-193-scope-tickets-writes-validate-fk into main
    3154fba ci: re-trigger Check (transient failure; green locally)
    bde8f81 Merge origin/main into fix/pms-193-scope-tickets-writes-validate-fk
    27fa80b Merge pull request 'fix(misc): correctness, concurrency, and test-reliability defects' (#208) from fix/pms-200-misc-correctness-concurrency-test-reliability into main
    7caf796 Merge origin/main into fix/pms-200-misc-correctness-concurrency-test-reliability
    a49cfbe Merge pull request 'fix(db,auth): dedupe migration prefix 041 and fix main compile' (#227) from fix/pms-293-dedupe-migration-prefix-041 into main
    2c9c7c3 fix(auth): return user: None in login_with_google mfa_required branch
    820cc4d fix(db): renumber portal_setup_tokens migration 041 to 042
    893f5d8 fix(auth): omit user profile in Google-callback mfa_required branch
    5b96470 Merge origin/main into fix/pms-200-misc-correctness-concurrency-test-reliability
    5946001 Merge pull request 'feat(portal): mint setup-link token + email on portal-access grant' (#204) from feat/pms-136-portal-setup-link into main
    c1b9663 Merge origin/main into feat/pms-136-portal-setup-link
    66367d5 Merge pull request 'fix(auth): close invite, signup, password, and validation defects' (#203) from fix/pms-192-invite-signup-password-validation into main
    52b32c5 Merge origin/main into fix/pms-192-invite-signup-password-validation
    8829844 Merge pull request 'fix(auth): close SSO/OIDC auth-strength and conformance gaps' (#202) from feat/pms-191-sso-oidc-security-gaps into main
    fbacbde Merge origin/main into feat/pms-191-sso-oidc-security-gaps
    3337ef3 Merge pull request 'fix(auth): close legacy PSA auth path security gaps' (#201) from fix/pms-190-legacy-auth-security-gaps into main
    7dd8b6a Merge origin/main into fix/pms-190-legacy-auth-security-gaps
    7e5fa28 fix(assets): allow 'deleted' in audit-log CHECK; add delete regression test
    269bf16 Merge pull request 'test(settings): fix stale billing route path in module-gating tests' (#225) from fix/pms-290-settings-stale-billing-path into main
    4c89552 fix(assets): wire configured AES key and harden vault crypto integrity
    a8589c0 test(settings): fix stale billing route path in module-gating tests
    f67057c feat(rls): activate RLS at runtime via split migrator/app DB roles
    8d564e0 Merge branch 'main' into chore/pms-201-remove-dead-stray-code
    6dfb9ee Merge pull request 'fix(startup): fail loud when configured SSO bootstrap fails' (#223) from fix/pms-289-sso-fail-loud-when-configured into main
    d79ab98 fix(startup): fail loud when configured SSO bootstrap fails
    86e40ab Merge pull request 'fix(tenants): seed lookup config for tenants reached off the PSA path' (#222) from feat/pms-288-seed-lookup-config-on-placement into main
    e0daef1 perf(tenants): cheap-guard the per-request sequence seed
    74adb16 fix(tenants): seed lookup config for tenants reached off the PSA path
    f75618f Merge pull request 'fix(tenants): set NOT-NULL kind in create_tenant; add regression test' (#221) from fix/pms-287-create-tenant-kind into main
    f7f8b7d fix(tenants): set NOT-NULL kind in create_tenant; add regression test
    8e2faad Merge pull request 'fix(startup): make migration failure fatal instead of warn-and-continue' (#219) from fix/pms-286-fatal-migrations into main
    b5ad162 Merge pull request 'feat(justfile): add dev-clean / dev-clean-all teardown recipes' (#214) from feat/dev-clean-recipes into main
    f82d9b3 Merge branch 'main' into feat/dev-clean-recipes
    398c0ba chore(cleanup): remove dead crates code and stray config/seed/test cruft
    a3333df fix(startup): make migration failure fatal instead of warn-and-continue
    842b18f chore(cleanup): remove dead and stray code from src/ tree
    303efb5 Merge pull request 'test(isolation): automate PMS-236 tenant-isolation QA across the API' (#216) from feat/pms-236-tenant-isolation-integration-test into main
    a3224a8 test(isolation): harden module-config and ticket_number checks
    f5520f7 fix: correct rmm, notifications, SLA, KB, portal, and contacts defects
    2c69eb9 test(isolation): automate PMS-236 tenant-isolation QA across the API
    6678777 test(settings): hit canonical /api/v1/invoices in module-gate tests
    5086c63 feat(justfile): add dev-clean / dev-clean-all teardown recipes
    9579f2b fix(contracts,billing): close financial-integrity gaps
    5f7c728 refactor: consolidate duplicated helpers, types, and test fixtures
    d68af1b fix(db): converge ticket filter builder; audit count_query placeholder family
    eaa150f fix(schema): harden migrations, FKs, seed, and truncation (PMS-196)
    0433815 fix(tickets): scope writes to tenant and validate FK references
    f69cc50 Merge pull request 'fix(rls): cover tenant-less tables; tenant-scope user_oauth_identities' (#207) from feat/pms-258-rls-cover-tenantless-tables into main
    eca763e Merge branch 'main' into feat/pms-258-rls-cover-tenantless-tables
    92bf278 fix(misc): correctness, concurrency, and test-reliability defects
    c224ffb fix(rls): cover tenant-less tables; tenant-scope user_oauth_identities
    3b508c1 Merge pull request 'refactor: converge duplicated subsystems and document architecture seams' (#206) from feat/pms-198-converge-subsystems into main
    f8029eb Merge branch 'main' into feat/pms-198-converge-subsystems
    a9ccf05 Merge pull request 'fix(audit): remove coarse per-request middleware that wrote unusable rows' (#198) from fix/pms-275-remove-coarse-audit-middleware into main
    c54ebe3 Merge branch 'main' into fix/pms-275-remove-coarse-audit-middleware
    1b55130 Merge pull request 'fix(ci): gate prod image push to main/tags; close CI coverage gaps' (#199) from fix/pms-189-ci-release-pipeline-drift into main
    9c0a400 Merge branch 'main' into fix/pms-189-ci-release-pipeline-drift
    0316824 refactor: converge duplicated subsystems and document architecture seams
    e7521d3 Merge pull request 'feat/pms-271-e2e-staging-prod-secrets' (#205) from feat/pms-271-e2e-staging-prod-secrets into main
    5807db8 fix(e2e): correct OIDC redirect_uri default to /auth/callback
    fb735aa refactor(e2e): name CI secrets after deployment variables
    0d33d0c feat(portal): mint setup-link token + email on portal-access grant
    2eb8977 fix(auth): close invite, signup, password, and validation defects
    222c649 Revert "fix(e2e): keep bare E2E_* as staging, add only E2E_PRODUCTION_"
    a4fef72 fix(auth): close SSO/OIDC auth-strength and conformance gaps
    d8e8eb0 fix(e2e): keep bare E2E_
    as staging, add only E2E_PRODUCTION_*
    ffb58e1 fix(auth): close legacy PSA auth path security gaps
    3221b6b Merge pull request 'feat(e2e): split CI env vars into staging/production secrets; manual prod opt-in' (#200) from feat/pms-271-e2e-staging-prod-secrets into main
    7788f76 feat(e2e): split CI env vars into staging/production secrets
    986a08e fix(ci): gate prod image push to main/tags; close CI coverage gaps
    6892bc4 fix(audit): remove coarse per-request middleware that wrote unusable rows
    730553a Merge pull request 'feat(migrations): no-op backfill + verification for co-mingled default-tenant rows' (#197) from feat/pms-263-comingled-backfill-verification into main
    2e65ee8 Merge branch 'main' into feat/pms-263-comingled-backfill-verification
    2e62ad8 Merge pull request 'test(isolation): per-user cross-isolation suite across modules' (#196) from feat/pms-264-per-user-isolation-suite into main
    8968aa0 feat(migrations): no-op backfill + verification for co-mingled default-tenant rows
    f71a7c6 test(isolation): per-user cross-isolation suite across modules
    a927e4e Merge pull request 'fix(workers): scope notification template lookup; audit from_trusted' (#195) from feat/pms-261-worker-from-trusted-audit into main
    2a9f970 fix(workers): scope notification template lookup; audit from_trusted
    6f54b2b Merge pull request 'refactor(domain): inject domains via env vars, never hardcode or fall back' (#192) from feat/pms-235-mokosh-domain-rebrand into main
    d155840 Merge branch 'main' into feat/pms-235-mokosh-domain-rebrand
    6cd85ca refactor(domain): inject all domains via env; drop hardcoded fallbacks
    2ef2fba Merge pull request 'fix(security): scope auth session methods to tenant; pin login-helper reachability' (#190) from feat/pms-260-cross-tenant-leak-fixes into main
    3c987d4 Merge branch 'main' into feat/pms-260-cross-tenant-leak-fixes
    4028957 Merge pull request 'feat(tenants): seed all editable lookups per tenant; reserve system-shared class' (#189) from feat/pms-259-seed-lookups-system-shared-class into main
    57804d1 fix(rls): renumber system-shared migration to 039; layer on PMS-257 fail-closed policy
    408d9bd Merge remote-tracking branch 'origin/main' into feat/pms-259-seed-lookups-system-shared-class
    100c59f Merge pull request 'feat(rls): flip tenant_isolation fail-closed with WITH CHECK and FORCE RLS' (#188) from feat/pms-257-rls-fail-closed into main
    6175e84 Merge branch 'main' into feat/pms-257-rls-fail-closed
    d8d2696 Merge pull request 'feat(tenant): remove the single-tenant cargo feature; no normal user lands in the default tenant' (#187) from feat/pms-262-remove-single-tenant-feature into main
    28e059f Merge branch 'main' into feat/pms-262-remove-single-tenant-feature
    50580b1 Merge pull request 'feat(db): route tenant-scoped service queries through begin_with_tenant' (#186) from feat/pms-256-rls-guc-plumbing into main
    c929e7c Merge branch 'main' into feat/pms-256-rls-guc-plumbing
    5da88eb Merge pull request 'docs(rls): per-user isolation reference and decomposition for PMS-255' (#185) from docs/pms-255-rls-isolation-plan into main
    18914ba Merge branch 'main' into docs/pms-255-rls-isolation-plan
    732427a Merge pull request 'chore: add pre-commit hook recipes' (#191) from chore/pre-commit-hooks into main
    22b4f59 Merge branch 'main' into chore/pre-commit-hooks
    106f983 Merge pull request 'fix(version): sanitise error bodies, warn on bad versions, test network path' (#194) from feat/pms-238-self-hosted-version-check into main
    fcf44f5 fix(version): sanitise error bodies, warn on bad versions, test network path
    35445fd Merge pull request 'feat(version): add self-hosted update check endpoint' (#193) from feat/pms-238-self-hosted-version-check into main
    551db74 feat(version): cache update-check result with a TTL
    e08a3ad feat(version): add self-hosted update check endpoint
    ebaa8d2 docs(domain): rebrand a8n.systems references to mokosh.systems (Bucket A)
    2a34180 chore: add install-hooks and pre-commit just recipes
    cbcfad6 fix(security): scope auth session methods to tenant; pin login-helper reachability
    78c5992 feat(tenants): seed all editable lookups per tenant; reserve system-shared class
    3476ed6 feat(rls): flip tenant_isolation fail-closed with WITH CHECK and FORCE RLS
    6969297 feat(tenant): remove the single-tenant cargo feature; no normal user lands in the default tenant
    bb76afb feat(db): route tenant-scoped service queries through begin_with_tenant
    864a0d8 docs(rls): per-user isolation reference and decomposition for PMS-255
    2f89fc7 Merge pull request 'feat(users): persist date_format_string preference on users (backend)' (#184) from feat/pms-253-date-format-preference-backend into main
    c57d5c6 feat(users): persist date_format_string preference on users (backend)
    a8116f3 Merge pull request 'chore(fmt): apply cargo fmt --all after PMS-244..PMS-249 sweep' (#183) from chore/pms-251-cargo-fmt-sweep into main
    990d585 chore(fmt): apply cargo fmt --all after PMS-244..PMS-249 sweep
    23b3259 Merge pull request 'test(auth): end-to-end placement tests for the bunyip login path (PMS-249)' (#182) from feat/mapps-249-bunyip-login-e2e into main
    9291524 test(auth): end-to-end placement tests for the bunyip login path (PMS-249)
    339e61b Merge pull request 'feat(invitations): email the invitee on invite create (PMS-246)' (#181) from feat/mapps-246-invite-email into main
    9d474ed Merge remote-tracking branch 'origin/main' into feat/mapps-246-invite-email
    85820e8 Merge pull request 'feat(auth): backfill default-tenant users off the shared tenant on login (PMS-245)' (#180) from feat/mapps-245-backfill-default-tenant-users into main
    9a752a6 feat(invitations): email the invitee on invite create (PMS-246)
    d8b05df feat(auth): backfill default-tenant users off the shared tenant on login (PMS-245)
    bf53e19 Merge pull request 'test(auth): pin the bunyip userinfo email_verified contract (PMS-248)' (#179) from chore/mapps-248-userinfo-email-verified-contract into main
    fd253a6 test(auth): pin the bunyip userinfo email_verified contract (PMS-248)
    f6c7d3f Merge pull request 'feat(invitations): tenant invite CRUD - Mokosh-owned org membership (PMS-244 phase 1)' (#178) from feat/mapps-244-invitations into main
    bd8ffd7 feat(auth): resolve SSO login to a tenant via Mokosh invites/self-signup (PMS-244, phase 2)
    b54b06c feat(invitations): tenant invite CRUD - Mokosh-owned org membership (PMS-244, phase 1)
    fa7724f Merge pull request 'feat(auth): lazily re-home default-tenant users to their org tenant (PMS-243)' (#177) from feat/mapps-243-rehome into main
    b78fa59 feat(auth): lazily re-home default-tenant users to their org tenant (PMS-243)
    59618ac Merge pull request 'feat(auth): resolve SSO users to a per-org tenant via the Bunyip org claim (PMS-240)' (#175) from feat/mapps-240-bunyip-org-tenant into main
    6b8ed51 feat(auth): resolve SSO users to a per-org tenant via the Bunyip org claim (PMS-240)
    bfb815f Merge pull request 'fix(seed): never auto-seed the shared Bunyip landing tenant (PMS-239)' (#174) from fix/mapps-239-demo-seed-shared-tenant into main
    18c60ef fix(seed): never auto-seed the shared Bunyip landing tenant (PMS-239)
    b2cf1b3 Merge pull request 'chore: cargo fmt --all after the PMS-139 TenantId sweep' (#173) from chore/cargo-fmt-after-pms-139-sweep into main
    c441b1c chore: cargo fmt --all after the PMS-139 TenantId sweep
    c7badab Merge pull request 'feat(auth): migrate the tickets hub to TenantId, completing PMS-139 (sweep batch 8)' (#171) from feat/pms-139-sweep-tickets into main
    17611c3 feat(auth): migrate the tickets hub to TenantId, completing PMS-139 (sweep batch 8)
    1ac0d22 Merge pull request 'feat(auth): migrate the notifications hub to TenantId (PMS-139 sweep batch 7)' (#169) from feat/pms-139-sweep-notifications into main
    d5c6133 feat(auth): migrate the notifications hub to TenantId (PMS-139 sweep batch 7)
    b4303f5 Merge pull request 'feat(auth): migrate the audit hub to TenantId (PMS-139 sweep batch 6)' (#167) from feat/pms-139-sweep-hubs into main
    f607764 feat(auth): migrate the audit hub to TenantId (PMS-139 sweep batch 6)
    23e36ba Merge pull request 'feat(auth): migrate contacts + billing to TenantId (PMS-139 sweep batch 5)' (#164) from feat/pms-139-sweep-contacts-billing into main
    3deb53e feat(auth): migrate contacts + billing to TenantId (PMS-139 sweep batch 5)
    e2a6de3 Merge pull request 'feat(auth): migrate knowledge_base + tenants + settings to TenantId (PMS-139 sweep batch 4)' (#163) from feat/pms-139-sweep-kb-tenants-settings into main
    0a1006d feat(auth): migrate knowledge_base + tenants + settings to TenantId (PMS-139 sweep batch 4)
    85e08a2 Merge pull request 'feat(auth): migrate calendar + sla + contracts to TenantId (PMS-139 sweep batch 3)' (#161) from feat/pms-139-sweep-calendar-sla-contracts into main
    b77e671 feat(auth): migrate calendar + sla + contracts to TenantId (PMS-139 sweep batch 3)
    c6b6adb Merge pull request 'feat(auth): migrate assets + projects to TenantId (PMS-139 sweep batch 2)' (#160) from feat/pms-139-sweep-assets-projects into main
    ee26720 feat(auth): migrate assets + projects to TenantId (PMS-139 sweep batch 2)
    622f3f4 Merge pull request 'feat(auth): migrate rmm + time_tracking to TenantId (PMS-139 sweep batch 1)' (#159) from feat/pms-139-sweep-rmm-time into main
    961251c feat(auth): migrate rmm + time_tracking to TenantId (PMS-139 sweep batch 1)
    1091d76 Merge pull request 'feat(auth): typed TenantId scoping foundation + reports migration (PMS-139)' (#158) from feat/pms-139-tenant-id-foundation into main
    2cc6511 feat(auth): typed TenantId scoping foundation + reports migration (PMS-139)
    a497e81 Merge pull request 'feat(timesheets): draft state + withdraw endpoint (PMS-183)' (#157) from feat/pms-183-timesheet-withdraw into main
    e75bdf9 feat(timesheets): draft state + withdraw endpoint for timesheets (PMS-183)
    45f51fc Merge pull request 'feat(audit): surface field-level before/after content in change history (PMS-204)' (#156) from feat/pms-204-history-content into main
    60f0e4f feat(audit): surface field-level before/after content in change history (PMS-204)
    9acd44a Merge pull request 'feat(projects): record task and project edits in the audit trail (PMS-184)' (#155) from feat/pms-184-task-edit-history into main
    6b20c9f Merge pull request 'feat(audit): per-record change-history endpoint (PMS-182)' (#154) from feat/pms-182-ticket-edit-history into main
    f123889 feat(projects): record task and project edits in the audit trail (PMS-184)
    110f532 feat(audit): per-record change-history endpoint for detail pages (PMS-182)
    caacdc9 Merge pull request 'docs: add 2026-06-06 platform audit to dev-docs/audits' (#153) from docs/add-platform-audit-2026-06-06 into main
    455e9cc docs: add 2026-06-06 platform audit to dev-docs/audits
    9cd4103 Merge pull request 'feat(billing): also surface invoice_number on payment responses (PMS-186)' (#150) from feat/pms-186-billing-company-name into main
    11bcb0e feat(billing): also surface invoice_number on payment responses (PMS-186)
    e450f5b Merge pull request 'feat(billing): include company_name on invoice and payment responses (PMS-186)' (#149) from feat/pms-186-billing-company-name into main
    6bbe7ff feat(billing): include company_name on invoice and payment responses (PMS-186)
    c32987c Merge pull request 'feat(reports): add safe custom report builder (PMS-180)' (#148) from feat/pms-180-custom-report-builder into main
    cc0023b feat(reports): add safe custom report builder (PMS-180)
    4bc54e0 Merge pull request 'feat(reports): add project + client report types end to end (PMS-179)' (#147) from feat/pms-179-project-client-reports into main
    148d3f6 feat(reports): add project + client report types end to end (PMS-179)
    92e77ea Merge pull request 'feat(seed): seed demo data on a new account's first visit (PMS-157)' (#146) from feat/pms-157-new-account-seeding into main
    b6f6ba1 fix(seed): make demo ticket seeding best-effort; document E2E kill-switch
    909dc07 feat(seed): seed demo data on a new account's first visit (PMS-157)
    aa6118f Merge pull request 'fix(contacts): 400 not 500 deleting a company with related records (PMS-170)' (#145) from fix/pms-170-company-delete-fk-400 into main
    7e13835 fix(contacts): return 400 not 500 when deleting a company with related records
    a86e802 Merge pull request 'fix(audit): correct SQL placeholder numbering in audit-log list (PMS-178)' (#144) from fix/pms-178-audit-list-placeholders into main
    7acb419 fix(audit): correct SQL placeholder numbering in audit-log list query
    ce0dc98 Merge pull request 'docs(e2e): spell out how to set the E2E account's admin role (SQL + bootstrap)' (#143) from docs/pms-155-e2e-admin-account into main
    d436054 Merge pull request 'feat(auth): translate Bunyip bunyip_role claim to mokosh role (PMS-172)' (#142) from feat/pms-172-bunyip-role-translation into main
    e950947 refactor(auth): clarify authz source + log Bunyip role transitions (PMS-172 review)
    8378289 feat(auth): translate Bunyip bunyip_role claim to mokosh role on the RS path
    0e3285b Merge pull request 'docs(e2e): how to set the E2E account admin role (SQL + bootstrap)' (#141) from docs/pms-155-e2e-admin-howto into main
    67c9cb8 docs(e2e): spell out how to set the E2E account's admin role (SQL + bootstrap)
    abd36b9 docs(e2e): spell out how to set the E2E account's admin role (SQL + bootstrap)
    3fcd925 Merge pull request 'docs(e2e): require admin role for the E2E account (PMS-155)' (#140) from docs/pms-155-e2e-admin-account into main
    e025056 docs(e2e): require admin role for the E2E account (PMS-155)
    f636e04 Merge pull request 'test(e2e): add API CRUD specs for time-tracking, projects, billing, contracts (PMS-155)' (#136) from feat/pms-155-e2e-core-modules into main
    8f878dd test(e2e): add API specs for RMM and the dispatch board (PMS-155 batch 4)
    007ba8b test(e2e): add API specs for notifications, settings, audit, reports (PMS-155 batch 3)
    fcf367f test(e2e): add API CRUD specs for calendar, SLA, assets, knowledge-base (PMS-155 batch 2)
    9aaeac6 test(e2e): make PMS-155 spec cleanup resilient to a single delete failure
    802a291 test(e2e): add API CRUD specs for time-tracking, projects, billing, contracts (PMS-155)
    c1dab9c Merge pull request 'fix(e2e): tolerate 405 on ticket delete until staging deploys PMS-149 route' (#135) from fix/pms-149-e2e-deploy-tolerant-ticket-delete into main
    289e772 fix(e2e): tolerate 405 on ticket delete until staging deploys PMS-149 route
    ba39edd Merge pull request 'feat(tickets): add DELETE /tickets/{id} so E2E cleans up its company (PMS-149)' (#133) from feat/pms-149-ticket-delete-route into main
    451fa6d fix(tickets): map ticket-delete FK violation to 400, not 500
    8a2e442 feat(tickets): add DELETE /tickets/{id} so E2E cleans up its company
    5cc3581 Merge pull request 'feat(e2e): un-fixme OIDC token-flow via replayed OP cookies (PMS-143)' (#132) from feat/pms-143-oidc-unfixme into main
    0de7285 chore(e2e): surface bunyip body on OIDC authorize non-3xx
    868658c fix(e2e): skip parent-domain derivation for IP literals
    0368bff feat(e2e): un-fixme OIDC token-flow via replayed OP cookies (PMS-143)
    853f9a1 Merge pull request 'test(e2e): re-fixme auth-ui pending PMS-148 login race' (#131) from fix/pms-148-refixme-auth-ui into main
    82418fc test(e2e): re-fixme auth-ui pending PMS-148 login race
    3e34835 Merge pull request 'feat(e2e): un-fixme auth-ui login + logout round-trip (PMS-142 v2)' (#130) from feat/pms-142-auth-ui-unfixme-v2 into main
    9b3cfe1 feat(e2e): un-fixme auth-ui login + logout round-trip (PMS-142 v2)
    5f850e7 Merge pull request 'chore(build): bump rust-builder-glibc to v1.0.1' (#127) from chore/bump-rust-builder-glibc-v1.0.1 into main
    0b7e68e Merge branch 'main' into chore/bump-rust-builder-glibc-v1.0.1
    5b184d2 Merge pull request 'feat(reports): GET /reports registry + integration tests (PMS-146)' (#129) from feat/pms-146-reports-registry-and-tests into main
    73e8682 feat(reports): add GET /reports registry + integration tests (PMS-146, closes PMS-93 gaps)
    cc4dcbd Merge pull request 'feat(assets): audited secret reveal, no plaintext in lists, tests (PMS-71)' (#128) from feat/pms-71-asset-secret-reveal-and-tests into main
    10b3760 feat(assets): stop leaking secrets in lists; add audited reveal endpoints + tests (PMS-71)
    78672ae chore(build): bump rust-builder-glibc to v1.0.1
    aac7c96 Merge pull request 'feat(projects): budget-vs-actual + time rollup + tests (PMS-51)' (#126) from feat/pms-51-project-actuals-and-tests into main
    5dc8acd feat(projects): compute budget-vs-actual, roll approved time into actuals, add tests (PMS-51)
    56e0a18 Merge pull request 'feat(portal): wire company-scoped invoices + add portal isolation tests (PMS-25)' (#125) from feat/pms-25-portal-invoices-and-tests into main
    7e0f275 feat(portal): wire company-scoped invoices + add portal isolation tests (PMS-25)
    bcf6f01 Merge pull request 'chore: Sync .gitignore' (#124) from chore/sync-gitignore into main
    86bbeca chore: Sync .gitignore
    70e2ae4 Merge pull request 'chore(e2e): capture access_token from /oauth2/token response, not just Bearer header' (#123) from chore/e2e-capture-spa-build-hash into main
    160688d chore(e2e): capture access_token from /oauth2/token response, not just Bearer header
    7619ecb Merge pull request 'chore(e2e): surface mokosh-apps SPA bundle hash in timeout diagnostic' (#122) from chore/e2e-capture-spa-build-hash into main
    cdf46ce chore(e2e): surface mokosh-apps SPA bundle hash in timeout diagnostic
    63ab9c1 Merge pull request 'fix(auth): JIT placeholder name no longer surfaces UUID fragments' (#121) from fix/jit-fallback-name-not-uuid-fragments into main
    37fcc9c fix(auth): JIT placeholder name no longer surfaces UUID fragments
    321520a Merge pull request 'feat(kb): one vote per user account for article ratings (toggle/switch)' (#120) from feat/kb-rating-per-user-votes into main
    f2e670f style: cargo fmt
    aeb0e56 feat(kb): make article ratings one vote per user account
    7a19fb6 Merge pull request 'feat(billing): generate recurring invoices from contract items (PMS-64 AC5)' (#119) from feat/pms64-recurring-invoicing into main
    a58c1db Merge branch 'main' into feat/pms64-recurring-invoicing
    4a4ec49 Merge pull request 'feat(kb): serve portal KB feed only via the portal-authed route' (#118) from feat/portal-kb-feed-auth into main
    bb0d8d2 Merge branch 'main' into feat/portal-kb-feed-auth
    98ec545 Merge pull request 'feat(notifications): backfill default rules for pre-existing tenants' (#117) from feat/notifications-seed-existing-tenants into main
    0f837be style: apply cargo fmt
    a1747d4 style: apply cargo fmt
    bd72ab6 style: apply cargo fmt
    e266dca feat(billing): generate recurring invoices from contracts (PMS-64 AC5)
    de3ebff feat(kb): serve portal KB feed only via portal-authed route
    d03ff7f feat(notifications): backfill default worker rules for existing tenants
    0c620dc Merge pull request 'fix(api): repair list ORDER BY misuse + time-entries count placeholders (PMS-145)' (#116) from fix/pms-145-time-entries-count-placeholders into main
    df0ce4b fix(api): repair list ORDER BY misuse + time-entries count placeholders
    66a1da9 Merge pull request 'fix(ci): cap integration-test parallelism to dodge sqlx-test pool timeout' (#115) from fix/check-pg-pool-saturation into main
    d531f38 Merge pull request 'feat(e2e): close PMS-142 - un-fixme the auth-ui login + logout round-trip' (#112) from feat/pms-142-auth-ui-unfixme into main
    eea87f3 fix(ci): cap integration-test parallelism to dodge sqlx-test pool timeout
    02c30e0 Merge pull request 'fix(billing): gate invoicing on timesheet approval (PMS-144)' (#114) from fix/pms-144-billing-approval-gate into main
    4bd93f4 fix(billing): gate invoicing on timesheet approval (ready_to_bill)
    d9abe84 Merge pull request 'feat(dev-sso): validate bunyip-issued tokens as a Resource Server' (#113) from feat/dev-sso-rs-trust-bunyip into main
    b6d9619 test(e2e): re-quarantine auth-ui - bunyip /logout does not kill OP session
    ce25821 feat(dev-sso): validate bunyip-issued tokens as a Resource Server
    8c50b19 test(e2e): tighten page-diagnostics API + use Error cause for original stack
    826e5b4 feat(e2e): close PMS-142 - un-fixme the auth-ui login + logout round-trip
    c94e090 Merge pull request 'feat(ci): close PMS-141 - promote E2E to merge gate on PRs to main' (#111) from feat/pms-141-e2e-merge-gate into main
    ae35028 feat(ci): close PMS-141 - promote E2E suite to merge gate on PRs to main
    b60a8d3 Merge pull request 'test(e2e): quarantine OIDC token-flow test - needs OP session cookie' (#110) from fix/e2e-oidc-fixme into main
    bfa3945 test(e2e): quarantine OIDC token-flow test - needs OP session cookie
    cab7078 Merge pull request 'fix(e2e): point OIDC test at the OP host, quarantine auth-ui round-trip' (#109) from fix/e2e-oidc-op-base-url-and-auth-ui-fixme into main
    dc5019e docs(e2e): refresh stale comments + README harness description
    718e6bb fix(e2e): point OIDC test at the OP host, quarantine auth-ui round-trip
    d9d3084 Merge pull request 'fix(e2e): capture bearer from ANY host, not just /api/v1' (#108) from fix/e2e-capture-bearer-any-host into main
    8a69f3f fix(e2e): capture bearer from ANY host, not just /api/v1
    95637bd Merge pull request 'fix(ci): pass E2E_TOTP_SECRET secret into the E2E job env' (#107) from fix/e2e-wire-totp-secret into main
    5bcaf8d fix(ci): pass E2E_TOTP_SECRET secret into the E2E job env
    319f8d2 Merge pull request 'feat(e2e): enter TOTP second factor during SPA login' (#106) from feat/e2e-totp-handling into main
    1a9e37e feat(e2e): enter TOTP second factor during SPA login
    4d46bf6 Merge pull request 'fix(e2e): treat /login/* as still IN the login flow' (#105) from fix/e2e-login-pathname-anchor into main
    88c274b fix(e2e): treat /login/* (e.g. /login/2fa) as still IN the login flow
    a90fbfb Merge pull request 'test(e2e): dump full URL/trail/request diagnostic when setup times out' (#104) from fix/e2e-bearer-diagnostics into main
    b30dc74 test(e2e): dump full URL/trail/request diagnostic when setup times out
    a383fb1 Merge pull request 'fix(e2e): probe data routes for bearer, merge auth-ui to dodge rate limit' (#103) from fix/e2e-spa-bearer-intercept-and-logout into main
    66e3433 test(e2e): harden auth-ui locators with .first(), tighten /api/v1 filter
    de17374 fix(e2e): force a post-login probe + merge auth-ui tests to dodge rate limit
    29d2eb8 Merge pull request 'fix(e2e): intercept SPA bearer for setup, click User-menu -> Logout' (#102) from fix/e2e-spa-bearer-intercept-and-logout into main
    30d66a9 test(e2e): refresh auth-state comment, drop dead routes.authLogin
    328ffbc fix(e2e): intercept SPA bearer for setup, click User-menu -> Logout
    4b01eef Merge pull request 'fix(ci): wait-for-deploy refetches missing trees, skips gate if unresolvable' (#101) from fix/e2e-wait-deploy-skip-when-unresolvable into main
    9c73dd1 fix(ci): wait-for-deploy refetches missing trees, skips gate if unresolvable
    6bf0e9a Merge pull request 'fix(ci): wait-for-deploy unshallows the clone when git log returns empty' (#100) from fix/e2e-wait-deploy-unshallow into main
    efea598 fix(ci): wait-for-deploy unshallows the clone when git log returns empty
    d47d72a Merge pull request 'fix(ci): resolve deploy-sync expected SHA to the last build-relevant commit' (#99) from fix/e2e-runner-toolcache into main
    6040838 fix(ci): resolve deploy-sync expected SHA to the last build-relevant commit
    8924692 Merge pull request 'test(e2e): aggregate-all-missing env vars in a preflight setup project' (#98) from fix/e2e-runner-toolcache into main
    104ed55 test(e2e): aggregate-all-missing env vars in a preflight setup project
    99738ad Merge pull request 'fix(ci): bake MOKOSH_GIT_HASH + describe + date into OCI build' (#97) from fix/e2e-runner-toolcache into main
    52742c6 fix(ci): bake MOKOSH_GIT_HASH + describe + date into OCI build
    256d17f Merge pull request 'fix(ci): API host is api.msp., not msp-api.' (#96) from fix/e2e-runner-toolcache into main
    3adb4a2 fix(ci): API host is api.msp., not msp-api.
    9d8b11a Merge pull request 'fix(ci): split E2E SPA host from API host, derive msp-api.' (#95) from fix/e2e-runner-toolcache into main
    3883fc8 fix(ci): split E2E SPA host from API host, derive msp-api.
    80a160e Merge pull request 'fix(ci): treat empty E2E_BASE_URL as missing, not as override' (#94) from fix/e2e-runner-toolcache into main
    0de6163 fix(ci): treat empty E2E_BASE_URL as missing, not as override
    e965450 Merge pull request 'fix(ci): drop playwright --with-deps - opensuse runner has no apt-get' (#93) from fix/e2e-runner-toolcache into main
    21ca57f fix(ci): drop playwright --with-deps - opensuse runner has no apt-get
    78ed118 Merge pull request 'fix(ci): hardcode RUNNER_TOOL_CACHE path - runner context unbound in job env' (#92) from fix/e2e-runner-toolcache into main
    020631b fix(ci): hardcode RUNNER_TOOL_CACHE path - runner context unbound in job env
    3f8c2a4 Merge pull request 'fix(ci): point E2E setup-node tool cache at RUNNER_TEMP' (#91) from fix/e2e-runner-toolcache into main
    55eb53c fix(ci): point E2E setup-node tool cache at RUNNER_TEMP
    aadb3bb Merge pull request 'PMS-140: Add Playwright E2E suite against staging, run on every merge to main' (#90) from feat/pms-140-e2e-playwright into main
    01a4d7d test(e2e): fix auth path, require OIDC redirect, harden teardown and CI
    b4ccc9a test(e2e): add Playwright suite against staging, run post-merge to main
    0c39d1e Merge pull request 'feat(auth): close PMS-138 - subdomain-driven tenant hint on login + forgot-password + Google JIT' (#89) from feat/pms-138-closeout into main
    c7d40ed feat(auth): close PMS-138 - subdomain-driven tenant hint on login + forgot-password + Google JIT
    4b4c1f4 Merge pull request 'fix(settings): drop legacy DELETE /settings/{id} - matchit conflict with /settings/{category}' (#88) from fix/settings-route-conflict into main
    a0d3d91 fix(settings): drop legacy DELETE /settings/{id} - matchit conflict with /settings/{category}
    934f96a Merge pull request 'feat(settings): close PMS-113 - unify module-config, add category endpoints + value validation, gate optional modules at runtime' (#87) from feat/pms-113-closeout into main
    606ba79 feat(settings): close PMS-113 - unify module-config, add category endpoints + value validation, gate optional modules at runtime
    63a1bfc Merge pull request 'feat(tenants): close PMS-21 - cfg-gate cleanup + module-config and cross-tenant tests' (#86) from feat/pms-21-closeout into main
    272d179 feat(tenants): close PMS-21 - cfg-gate cleanup + module-config and cross-tenant tests
    7a34463 Merge pull request 'fix(list-queries): correct WHERE param numbering for count_query in 6 list_* methods' (#85) from fix/list-count-query-param-mismatch into main
    6acbb23 fix(list-queries): correct WHERE param numbering for count_query in 6 list_* methods
    68580e0 Merge pull request 'fix(migrations): rename PMS-4 recovery-codes migration 027 -> 029 (version collision with PMS-106)' (#84) from fix/migration-027-collision into main
    7edbf13 fix(migrations): rename PMS-4 recovery-codes migration 027 -> 029 (version collision with PMS-106)
    4d995d4 Merge pull request 'feat(auth): close PMS-4 - list filter, layered rate limit, MFA recovery codes, tenant hardening' (#83) from feat/pms-4-closeout into main
    387e18d Merge pull request 'feat(calendar): appointment reminders worker (PMS-58)' (#81) from feat/pms-58-calendar-reminders into main
    e922e0f Merge branch 'main' into feat/pms-58-calendar-reminders
    d00c3d0 Merge remote-tracking branch 'origin/main' into feat/pms-58-calendar-reminders
    6a0e444 Merge pull request 'feat(audit): record billing + contracts mutations in the audit log (PMS-117)' (#82) from feat/pms-117-audit-hooks into main
    be05264 Merge branch 'main' into feat/pms-117-audit-hooks
    ef0ffbf feat(audit): record billing + contracts mutations in the audit log (PMS-117)
    35704a5 Merge pull request 'feat(sla): at-risk + breach notifications via sweep worker (PMS-106)' (#80) from feat/pms-106-sla-notify into main
    1d020fb feat(calendar): appointment reminders worker (PMS-58)
    d25444b feat(auth): close PMS-4 - list filter, layered rate limit, MFA recovery codes, tenant hardening
    e1244a0 feat(sla): at-risk + breach notifications via sweep worker (PMS-106)
    242360a Merge pull request 'feat(calendar): RRULE expansion + dispatch view (PMS-58)' (#77) from feat/pms-58-calendar into main
    8874be8 Merge branch 'main' into feat/pms-58-calendar
    bdcb4d5 Merge pull request 'feat(contracts): hour-balance consumption, rate resolution, lifecycle (PMS-64)' (#75) from feat/pms-64-contracts into main
    0fd9124 Merge remote-tracking branch 'origin/main' into feat/pms-58-calendar
    39950bf Merge remote-tracking branch 'origin/main' into feat/pms-64-contracts
    269c79d Merge pull request 'feat(kb): publish lifecycle, slug uniqueness, version restore, trigram search, feedback, portal feed (PMS-79)' (#78) from feat/pms-79-kb into main
    89fd6fd Merge branch 'main' into feat/pms-79-kb
    dbf8c91 feat(kb): publish lifecycle, slug uniqueness, version restore, trigram search, feedback, portal feed (PMS-79)
    f1d7e99 Merge pull request 'feat(billing): generate invoices from billable time entries (PMS-33)' (#76) from feat/pms-33-billing into main
    c7884b1 Merge branch 'main' into feat/pms-33-billing
    025f6d3 Merge pull request 'feat(sla): business-hours-aware SLA clock engine (PMS-106)' (#72) from feat/pms-106-sla-clock into main
    bc9e86a Merge branch 'main' into feat/pms-106-sla-clock
    1cff709 Merge pull request 'feat(audit): record entity mutations + auth events (PMS-117)' (#70) from feat/pms-117-audit-log into main
    d5e9b1b feat(calendar): RRULE expansion + dispatch view (PMS-58)
    ba69f11 Merge remote-tracking branch 'origin/main' into feat/pms-64-contracts
    d807030 Merge remote-tracking branch 'origin/main' into feat/pms-106-sla-clock
    f7f08c1 Merge remote-tracking branch 'origin/main' into feat/pms-117-audit-log
    7396d1b feat(billing): generate invoices from billable time entries (PMS-33)
    9c14ffa feat(contracts): hour-balance consumption, rate resolution, lifecycle (PMS-64)
    a3ebcd0 Merge pull request 'test(pms-11): cover assign + assert JOINed ticket DTO fields (F3)' (#73) from feat/pms-11-tickets-assign-joined-fields-test into main
    fca3248 Merge pull request 'fix(contacts): make update_company and update_contact persist every UpdateRequest field' (#74) from feat/pms-17-tests into main
    ef5af80 test(pms-11): cover assign + assert JOINed ticket DTO fields (F3)
    3bbf1e5 fix(contacts): make update_company and update_contact persist every Update
    Request field
    6bd23e4 feat(sla): business-hours-aware SLA clock engine (PMS-106)
    e489d7a Merge pull request 'test(pms-17): integration tests pinning F4 fix + site/contact CRUD + portal flag + F9 filter' (#71) from feat/pms-17-tests into main
    e1aec1a test(pms-17): integration tests pinning F4 fix + site/contact CRUD + portal flag + F9 filter
    708d322 feat(audit): record entity mutations + auth events in the audit log
    a305bca Merge pull request 'feat(scheduler): shared background-job runner (PMS-135)' (#69) from feat/pms-135-scheduler into main
    3895e17 fix(scheduler): address code-review findings on shared scheduler (PMS-135)
    887dbd7 feat(scheduler): shared background-job runner (PMS-135)
    0d4c473 Merge pull request 'feat(api): readiness probe at /api/v1/ready (PMS-130)' (#68) from feat/pms-130-readiness into main
    bbe9855 fix(api): address code-review findings on /ready (PMS-130)
    6174aa4 feat(api): readiness probe at /api/v1/ready (PMS-130)
    69364fc Merge pull request 'feat(types): extract shared DTOs into mokosh-types workspace crate (PMS-129)' (#67) from feat/pms-129-mokosh-types into main
    99ca90e fix(types): add serde_json dep + refresh Cargo.lock for new crate (PMS-129)
    02fa99f fix(types): replace AppError reference with crate-local AuthRequired marker (PMS-129)
    5454f62 feat(types): extract shared DTOs into a mokosh-types workspace crate (PMS-129)
    e24ff59 Merge pull request 'feat(migrations): split 1688-line initial schema into per-feature files (PMS-128)' (#66) from feat/pms-128-migration-split into main
    813c1c1 feat(migrations): split 1688-line initial schema into per-feature files (PMS-128)
    666913f Merge pull request 'feat(api): paginate every list handler (PMS-127)' (#65) from feat/pms-127-pagination into main
    a03bfff docs(pagination): clarify audit-log cap drop + dual-Query convention
    91e1a40 feat(api): route every list handler through utils/pagination (PMS-127)
    46a45a1 Merge pull request 'feat(tracing): named instrument spans on every service method (PMS-126)' (#64) from feat/pms-126-tracing-spans into main
    529e778 feat(tracing): add named instrument spans on every service method (PMS-126)
    6c80f4c Merge pull request 'feat(router): self-documenting 501 body for placeholder modules (PMS-125)' (#63) from feat/pms-125-stub-bodies into main
    d5044c0 style: allow dead_code on common::{seed_admin,login} for unauthenticated test binaries
    d8ae8af style: rewrap assert! to satisfy rustfmt in dispatch_stub test
    0940a9d style: reflow long lines for rustfmt in PMS-125 stub
    f421318 feat(router): self-documenting 501 body for placeholder modules (PMS-125)
    bf5c42a Merge pull request 'feat(rmm): device-sync worker, provider trait, suppression + dedupe (PMS-103)' (#62) from feat/pms-103-rmm-sync-worker into main
    0dfea6d style: drop unused RmmService accessor methods
    6aefab3 style: apply rustfmt to PMS-103 rmm sync worker work
    1840992 feat(rmm): sync worker, provider trait, prefs/dedupe, encryption key wire-up
    9889f59 Merge pull request 'feat(notifications): dispatcher worker, prefs, encryption (PMS-92)' (#61) from feat/pms-92-notifications-dispatcher into main
    09e5435 style(tests): factor notifications row tuple into NotifRow alias
    4f43203 style: blank line between bullet list and paragraph in dispatch doc
    76a54d7 style: apply rustfmt to PMS-92 notifications dispatcher work
    d3717d4 feat(notifications): dispatcher worker, preference enforcement, encryption key wire-up
    98d3aa7 Merge pull request 'fix(auth): seed first_name/last_name defaults on bunyip JIT user upsert' (#60) from feat/jit-user-name-defaults into main
    7dceaf6 fix(auth): seed first_name/last_name defaults on bunyip JIT user upsert
    d775285 Merge pull request 'feat(contacts): populate CompanyResponse rollup fields' (#59) from feat/crm-ops into main
    abc2bc4 feat(contacts): populate CompanyResponse rollup fields
    7747fb4 Merge pull request 'feat(time-tracking): rounding, rate derivation, timesheet approval, tenant scoping' (#58) from feat/time-tracking-resolve-rounding into main
    d0acbb5 feat(time-tracking): apply rounding, derive rates, add timesheet approval + tenant scoping
    248e135 Merge pull request 'fix/dev-sso-private-network-name' (#57) from fix/dev-sso-private-network-name into main
    dd34ae9 fix(dev): drop server's depends_on infisical so compose project is valid
    0aaa5f2 fix(dev-sso): match overlay private network name to base per-user name
    87cac87 Merge pull request 'style(tests): rustfmt wrap on hash_password call' (#56) from fix/pms-124-fmt-wrap into main
    81a294c fix(tickets): cast sla_targets DECIMAL columns to float8 for sqlx decode
    fb96025 test(common): init tracing subscriber so the real sqlx error surfaces
    2de1bd8 fix(tests): send custom_fields: {} on create ticket, surface error body
    81487c8 fix(ci): point DATABASE_URL at the postgres service name, not localhost
    c4727dc style(tests): allow dead_code on per-binary-unused common items
    e56e42a style(tests): rustfmt wrap on hash_password call
    cc5f7c3 Merge pull request 'feat(tests): module-level integration tests for real route groups (F10)' (#55) from feat/pms-124-integration-tests into main
    806312f fix(tests): authenticate via Authorization: Bearer, not a cookie jar
    d172c15 feat(tests): module-level integration tests for real route groups (F10)
    3b62355 Merge pull request 'feat(api): add length validation to all Filter query types (F9)' (#54) from feat/pms-123-filter-validate into main
    7b67a7a docs(kb): note ILIKE cap rationale on KbArticleFilter.q
    b7c612f feat(api): add length validation to all Filter query types (F9)
    53450bf Merge pull request 'style(auth): cargo fmt oidc_rs.rs' (#53) from fix/oidc-rs-fmt into main
    9c3dffd style(auth): cargo fmt oidc_rs.rs
    52a790d Merge pull request 'feat/bunyip-op-cutover' (#52) from feat/bunyip-op-cutover into main
    cae15d2 feat(auth): wire bunyip RS verifier into AuthMiddleware
    cf2ff21 feat(auth): implement Resource-Server at+jwt verifier
    8131438 feat(auth): scaffold Resource-Server OIDC verifier (bunyip-as-OP cutover)
    d351093 Merge pull request 'feat/fix-just-dev-wont-start-infisical' (#51) from feat/fix-just-dev-wont-start-infisical into main
    de6da3a rewrite comment for dev-down and dev-clean
    d286b3a fix comment
    ef1649a add start infisical recipe
    0b3727c add tag
    eabf8e4 Merge pull request 'fix(ci): generate release notes from commits since previous tag' (#50) from fix/release-notes-since-prev-tag into main
    dd7f0fd fix(ci): generate release notes from commits since previous tag
    5b5eef0 Merge pull request 'fix/db-migrations-in-app' (#49) from fix/db-migrations-in-app into main
    0c9a066 WIP: Build on every push
    3d2b51a WIP: Build on every push
    82b3044 WIP: Build on every push
    562f8e4 fix(migrations): move mokosh_auth schema/columns into app migrations
    9b551af Merge pull request 'PSA audit: auth + tenancy security fixes' (#48) from feat/m1-vas into main
    dc202a9 fix(test): bind reset-token strings before borrowing (E0716)
    1b2568e fix(router): use api.msp host prefix in not_a_frontend fallback
    033b6bc style: cargo fmt --all
    92c485e test(auth): unit-test reset-token parsing + super-admin email allowlist
    ddaaeeb ci: publish the server image as mokosh-server (single name)
    6f406d3 ci: publish the server image as both mokosh-server and mokosh-api
    71e65ce fix(db): parameterize RLS tenant GUC; drop ineffective with_tenant
    1d5ac98 feat(auth): harden Google OAuth (verified-email link, email allowlist, fail-closed)
    5e0af57 fix(tenancy): validate cross-tenant foreign keys on create/update
    bd1d794 fix(auth): bind reset tokens to user; gate sign-in on tenant status
    6c50a88 Merge pull request 'fix(dev-sso): route Traefik labels on Compose 2.40 + shared Traefik' (#47) from fix/dev-sso-traefik-label-interpolation into main
    d13ba40 fix(dev-sso): route Traefik labels correctly on Compose 2.40 + shared Traefik
    c170baa Merge pull request 'docs: quickstart for fresh clones + CLAUDE.md' (#46) from docs/quickstart into main
    a05771a docs: add quickstart for fresh clones, plus CLAUDE.md
    e1ddf6f Merge pull request 'fix(ci): trigger image build on crates/
    edits + add manual dispatch' (#45) from fix/ci-trigger-crates into main
    6cb9513 fix(ci): trigger image build on crates/** edits + add manual dispatch
    3fdc0ef Merge pull request 'feat(ci): use $RUNNER_TEMP instead of /tmp in claude-fix workflow' (#44) from feat/pms-132-no-tmp into main
    bcd0990 feat(ci): guard against unset RUNNER_TEMP before using it
    54f1941 feat(ci): use $RUNNER_TEMP instead of /tmp in claude-fix workflow
    11fc65b Merge pull request 'fix(clippy): use ok_or instead of ok_or_else for plain HttpError values' (#43) from fix/clippy-sessions-ok-or into main
    1f83ca5 fix(clippy): use ok_or instead of ok_or_else for plain HttpError values
    d2e9177 Merge pull request 'Implementing SSO, OIDC (All auth)' (#42) from feature-sso into main
    09751b3 Merge remote-tracking branch 'origin/main' into feature-sso
    ce3f90f feat(oidc): fan back-channel logout out on RP-initiated /oauth2/logout
    93883ed feat(extractor): BearerUser rejects tokens from revoked op_sessions
    0b99014 feat(auth): emit back-channel logout to every registered RP on /v1/auth/logout
    97af972 Merge pull request 'feat(justfile): fj-driven create-release + group attrs (DEV-331)' (#41) from feat/justfile-fj-pr-create-DEV-331 into main
    778a440 feat(justfile): fj-driven create-release + group attrs (DEV-331)
    4353d52 log 5xx errors with underlying AuthError detail
    8a0b75f Merge pull request 'feat: consolidate PMS server PRs (PMS-4..PMS-131)' (#40) from feat/pms-merge into main
    9fa4c00 fix(clippy): resolve remaining workspace clippy warnings for -D warnings
    ff7413d fix(clippy): apply machine-applicable clippy suggestions
    0db5161 style: cargo fmt --all; suppress two pre-existing clippy lints in mokosh-auth-core
    01ebd03 ci(check): add fmt + clippy + compile + tests workflow
    01aefb8 Merge remote-tracking branch 'origin/chore/claude-fix-workflow' into feat/pms-merge
    13d5dda Merge remote-tracking branch 'origin/feat/audit-story-pms-117' into feat/pms-merge
    52ad3ac Merge remote-tracking branch 'origin/feat/settings-story-pms-113' into feat/pms-merge
    be878e7 Merge remote-tracking branch 'origin/feat/sla-story-pms-106' into feat/pms-merge
    0862e7f Merge remote-tracking branch 'origin/feat/rmm-story-pms-100' into feat/pms-merge
    d1d4efb Merge remote-tracking branch 'origin/feat/reports-story-pms-93' into feat/pms-merge
    a057e56 Merge remote-tracking branch 'origin/feat/notifications-story-pms-85' into feat/pms-merge
    6023551 Merge remote-tracking branch 'origin/feat/kb-story-pms-79' into feat/pms-merge
    c415e73 Merge remote-tracking branch 'origin/feat/assets-story-pms-71' into feat/pms-merge
    b718b3f Merge remote-tracking branch 'origin/feat/contracts-story-pms-64' into feat/pms-merge
    236e484 Merge remote-tracking branch 'origin/feat/calendar-story-pms-58' into feat/pms-merge
    62b9643 Merge remote-tracking branch 'origin/feat/projects-story-pms-51' into feat/pms-merge
    b239c93 Merge remote-tracking branch 'origin/feat/time-tracking-story-pms-42' into feat/pms-merge
    c166d47 Merge remote-tracking branch 'origin/feat/billing-story-pms-33' into feat/pms-merge
    7ea90af Merge remote-tracking branch 'origin/feat/portal-story-pms-25' into feat/pms-merge
    40d26ac Merge remote-tracking branch 'origin/feat/tenants-story-pms-21' into feat/pms-merge
    66f1da3 Merge remote-tracking branch 'origin/feat/contacts-story-pms-17' into feat/pms-merge
    e957286 Merge remote-tracking branch 'origin/feat/tickets-story-pms-11' into feat/pms-merge
    a35b3f0 Merge remote-tracking branch 'origin/feat/auth-story-pms-4' into feat/pms-merge
    e2fb8b2 ci: add claude-fix workflow
    47b3574 fix(justfile): register lets-chat with per-provider redirect_uri slug
    02deaed feat(audit): scaffold + writer middleware + read endpoint
    43b1c1f feat(settings): scaffold + tenant settings + module configs
    f4a2d8a feat(sla): scaffold + policies, targets, business hours, holidays, evaluator
    ff4b78e feat(rmm): scaffold + connections, device mappings, alert rules, ingest
    25ea790 feat(reports): scaffold + dashboard, tickets, time, billing, CSV export
    fe702cc feat(notifications): scaffold + channels, templates, prefs, inbox, rules, dispatcher
    d1812ea feat(kb): scaffold + categories, articles, versioning, portal feed
    ffce981 feat(assets): scaffold + asset types, assets, relationships, CIs, credentials, audit
    7298b90 feat(contracts): scaffold + CRUD for contracts, items, balances, rate cards
    24ddf81 feat(calendar): scaffold + appointments, availability, time-off, on-call
    96ce98b feat(projects): scaffold + projects, phases, task statuses, tasks, dependencies
    adaa594 feat(time-tracking): implement work types, time entries, timesheets, timers, rounding rules
    cefa9ac feat(time-tracking): scaffold module + wire router (PMS-43)
    f31778b feat(billing): tax rates CRUD + jurisdiction lookup
    81da537 feat(billing): payment gateway configs CRUD with at-rest encryption
    d3de7f1 feat(billing): payments CRUD with invoice-status reconciliation
    e67030c feat(billing): PUT /api/v1/invoices/:id with frozen-status guard
    47a0ae4 feat(billing): POST /api/v1/invoices with atomic sequence + line items
    44e178f feat(billing): GET /api/v1/invoices/:id with lines
    04e89de feat(billing): GET /api/v1/invoices paginated + filterable (F7)
    5105a8a feat(billing): scaffold module + wire router (PMS-34)
    fed6a72 feat(portal): GET /api/v1/portal/kb placeholder pending PMS-79
    28775fc feat(portal): GET /api/v1/portal/invoices/:id placeholder pending PMS-33
    73d99e2 feat(portal): GET /api/v1/portal/invoices placeholder pending PMS-33
    ab0b9f2 feat(portal): GET /api/v1/portal/tickets/:id with cross-company 404
    60488bc feat(portal): GET /api/v1/portal/tickets lists company-scoped tickets
    b06c6b0 feat(portal): POST /api/v1/portal/tickets creates contact-scoped ticket
    c1d6b7a feat(portal): contact-scoped session + portal auth middleware (F6)
    c38cdea feat(router): gate /api/v1/tenants behind the multi-tenant feature
    3bcfe6f feat(auth): TenantScope extractor for explicit tenant-id propagation
    2b634ab chore(router): drop the dead /companies alias
    e00a272 feat(contacts): honor create_portal_access on create_contact
    06de4ab feat(tickets): dispatch notifications + webhooks from automation rules
    7bb0df5 feat(tickets): send email when add_note has send_email = true
    eaf66db fix(tickets): join lookup tables into TicketResponse (F3)
    e90708c feat(auth): personal API key CRUD (issue / list / revoke)
    3a9cb3f feat(auth): implement MFA TOTP verification + enrollment endpoints
    8ce5238 feat(auth): send welcome email on admin user creation
    d67f8bf feat(auth): send password reset email via Mailer trait
    e2eff78 Merge pull request 'Revert M1 image distribution work' (#19) from revert/m1-image-distribution into main
    b573fc4 Revert M1 image distribution work
    848fcc3 Merge pull request 'ci: fix QEMU binfmt registration for arm64 cross-build' (#18) from feat/m1-image-distribution into main
    fa7ab7d ci: fix QEMU binfmt registration for arm64 cross-build
    89d19f4 Merge pull request 'ci: register QEMU binfmt inline instead of via setup-qemu-action' (#17) from feat/m1-image-distribution into main
    a74fbd5 ci: register QEMU binfmt inline instead of via setup-qemu-action
    2444c15 Merge pull request 'feat/m1-image-distribution' (#16) from feat/m1-image-distribution into main
    36b647e docs(operator): document container registry auth for self-hosters
    fcb323e feat(m1): operator compose.yml + update check + multi-arch build
    dc17aee Merge pull request 'fix(oci): drop image.source label causing dual-org package listing' (#15) from fix/drop-oci-source-label into main
    87a85b6 fix(oci): drop image.source label causing dual-org package listing
    bc546f0 chore(justfile): add register-lets-chat-client recipe (sso M1)
    a253ef3 feat(users): protect Owner memberships from other admins
    c097ae3 fix(auth): switch_active_tenant rebinds new token to caller's op_session
    8ac097a feat(audit): filter extensions + CSV export (item 7 server)
    e0575bd feat(sessions): admin endpoints to list+revoke another user's sessions
    139d71b Merge pull request 'feat: multi-origin CORS + msp-api placeholder + calendar route stub' (#14) from feat/cors-multi-origin-and-placeholder into main
    7beb7a4 security: stop tracking .env.dev; gitignore future copies
    4fb15b2 docs: milestone-1 handoff for the PSA Systems v0.1.0 cutover

    Downloads