-
v0.4.0
StableAll checks were successfulBuild OCI container / Build and push mokosh-server image (push) Successful in 5m12sreleased this
2026-06-30 17:33:32 +02:00 | 299 commits to main since this releaseChangelog
2e6ba89Merge pull request 'Release v0.4.0' (#407) from release/v0.4.0 into main
4119b20Merge branch 'main' into release/v0.4.0
9f5e7fcMerge pull request 'fix(e2e): settle hub login form before fill + URL-based 2FA advance signal' (#409) from fix/PMS-595-chromium-credential-resubmit-settle into main
4cf23bdfix(e2e): settle hub login form before fill + URL-based 2FA advance signal
026120bfix(e2e): recover chromium SPA login from credential-form re-render race
60d9b9cRelease v0.4.0
3bafb3cMerge pull request 'fix(auth): explicit Validation::new(Algorithm::HS256) + mint iss/aud/nbf claims' (#406) from fix/MAPPS-334-explicit-validation-secret-floor-v2 into main
92ed8c1fix(auth): disable validate_aud until strict iss/aud flip lands
a6db9f5Merge pull request 'fix(auth): bind userinfo.sub == claims.sub; truthful email_verified_at' (#404) from fix/MAPPS-335-sub-binding-and-email-verified-truth into main
d387ebdMerge pull request 'fix(auth): kid-aware JWKS refresh + cap force-refresh cadence + active checks on legacy fallback' (#405) from fix/MAPPS-337-jwks-kid-aware-redirect-cap-active-checks into main
5722869fix(auth): kid-aware JWKS refresh + cap force-refresh cadence + active checks on legacy fallback
9e70eccfix(auth): bind userinfo.sub == claims.sub; truthful email_verified_at
ab59925fix(auth): explicit Validation::new(Algorithm::HS256) + mint iss/aud/nbf claims
4a857d2Merge pull request 'fix(config): refuse to boot with a dev-default JWT_SECRET outside dev/test (PMS-497)' (#370) from fix/PMS-497-jwt-secret-production-guard into main
19dc713Merge pull request 'feat(api): emit security response headers on every response (PMS-388)' (#367) from feat/PMS-388-app-level-security-headers into main
102b80bMerge pull request 'fix(dev): bind dev Postgres to loopback and reject public LAN IP' (#399) from fix/dev-db-loopback-bind-on-main into main
7aa5e68Merge branch 'main' into fix/PMS-497-jwt-secret-production-guard
1854d64Merge pull request 'feat(roles): every mokosh user is an admin of their own instance' (#401) from feat/MAPPS-330-everyone-is-mokosh-admin into main
39395edMerge branch 'main' into feat/PMS-388-app-level-security-headers
7da858bMerge pull request 'fix(auth): cap + anti-replay TOTP verification on agent login' (#400) from fix/PMS-502-mfa-totp-attempt-cap-anti-replay into main
7fe6aeaMerge branch 'main' into feat/PMS-388-app-level-security-headers
1c9c4faMerge main: drop superseded postgres-loopback hunk, keep justfile RFC1918 filter
0fb2d21chore(migrations): renumber MAPPS-330 backfill 084 -> 085
0ac0b6fMerge pull request 'fix(e2e): deflake firefox form-validation by waiting for nav links to be visible' (#402) from fix/PMS-543-firefox-nav-visible-wait into main
f3f1e49fix(e2e): wait for nav links to be visible to deflake firefox form-validation
9c49820fix(migration): drop nonexistent users.deleted_at guard from MAPPS-330 backfill
cf5860bfeat(roles): every mokosh user is an admin of their own instance
9f61780fix(auth): cap + anti-replay TOTP verification on agent login
c8f2250Merge pull request 'fix(dev): bind app Postgres to loopback and fail loud on missing DB secrets (PMS-496)' (#392) from fix/PMS-496-postgres-loopback-bind-fail-loud-secrets into main
b9f0cffMerge branch 'main' into fix/PMS-496-postgres-loopback-bind-fail-loud-secrets
071b3ddfix(dev): bind dev Postgres to loopback and reject public LAN IP
f8ea1f8Merge pull request 'test(e2e): expect inline "Company is required." copy on new-ticket form (PMS-535)' (#394) from fix/PMS-535-company-required-copy into main
508fcebfix(config): repair merge tail + drop superseded validate_jwt_secret (PMS-497)
7c400b9test(e2e): expect inline "Company is required." copy on new-ticket form (PMS-535)
b99cb20Merge remote-tracking branch 'origin/main' into feat/PMS-388-app-level-security-headers
f7091aeMerge remote-tracking branch 'origin/main' into fix/PMS-497-jwt-secret-production-guard
72975a0ci: re-trigger E2E against staging (PMS-496)
9f74f7cMerge remote-tracking branch 'origin/main' into fix/PMS-496-postgres-loopback-bind-fail-loud-secrets
8007fb9Merge pull request 'Derive OCI publish mode from trigger to stop twin-publish race (GOV-15)' (#382) from fix/GOV-15-twin-trigger-publish-mode into main
817b4d9Merge branch 'main' into fix/GOV-15-twin-trigger-publish-mode
021897aMerge pull request 'test(kb): format assert_eq! in top-driving test, land coverage (PMS-533)' (#393) from fix/PMS-533-kb-test-rustfmt into main
f859ec0test(kb): format assert_eq! in top-driving test, land coverage (PMS-533)
300c0abfix(dev): bind app Postgres to loopback and fail loud on missing DB secrets (PMS-496)
a0e3b64Merge pull request 'ci(e2e): usebun xinstead of missingbunxshim (PMS-532)' (#391) from fix/PMS-532-e2e-bunx-shim into main
a1a1ef9ci(e2e): usebun xinstead of missingbunxshim (PMS-532)
233c31aMerge pull request 'feat(dev): ensure-env generates all self-owned secrets (PMS-490)' (#390) from feat/PMS-490-ensure-env-generates-secrets into main
75c11b9feat(dev): ensure-env generates all self-owned secrets (PMS-490)
d1f0b51Merge pull request 'chore(auth): drop stale crates/mokosh-auth-http comment refs (PMS-295)' (#389) from feat/PMS-295-remove-mokosh-auth-mechanism-2 into main
88b5a47chore(auth): drop stale crates/mokosh-auth-http comment refs (PMS-295)
1c619d7feat(auth): remove mokosh-auth; bunyip-as-OP is the sole OP (PMS-295)
d29284eMerge pull request 'feat(workflows): add ticket templates for new-ticket pre-fill (PMS-448)' (#387) from feat/PMS-448-ticket-templates into main
eb20ab6feat(workflows): add ticket templates for new-ticket pre-fill (PMS-448)
443e2e7ci(e2e): run E2E on opensuse-dev runner with pre-baked Playwright (PMS-423)
4145f0dMerge pull request 'feat(portal): rate-limit and lock out brute-force portal logins (PMS-501)' (#385) from feat/PMS-501-portal-login-rate-limit-lockout into main
9f431b3feat(portal): rate-limit and lock out brute-force portal logins (PMS-501)
06166acMerge pull request 'feat(time-tracking): split billable from worked minutes per entry (PMS-395)' (#384) from feat/PMS-395-billable-minutes-split into main
0ddb5d8feat(time-tracking): split billable from worked minutes per entry (PMS-395)
ac07565Merge pull request 'fix(config): require 64-hex ENCRYPTION_KEY outside dev/test (PMS-498)' (#383) from fix/PMS-498-require-hex-encryption-key-in-prod into main
cb2789efix(config): require 64-hex ENCRYPTION_KEY outside dev/test (PMS-498)
4ae07e4fix(ci): derive publish mode from trigger to stop twin-publish race
df0090aMerge pull request 'feat(db): self-provision split DB roles at startup (PMS-489)' (#381) from feat/PMS-489-self-provision-db-roles into main
c73584afeat(db): self-provision split DB roles at startup (PMS-489)
8daf44dMerge pull request 'fix(auth): enforce role ceiling on create_user (PMS-503)' (#380) from fix/PMS-503-create-user-role-ceiling into main
10f4a2cfix(auth): enforce role ceiling on create_user (PMS-503)
6d92b7bMerge pull request 'feat(email-intake): store inbound email attachments on the ticket (PMS-450)' (#379) from feat/PMS-450-email-intake-attachments into main
8a5cf9afeat(email-intake): store inbound email attachments on the ticket (PMS-450)
9999177Merge pull request 'fix(config): refuse dev JWT_SECRET/ENCRYPTION_KEY outside dev/test (PMS-499)' (#378) from fix/PMS-499-guard-dev-secrets-in-prod into main
aaad18cfix(config): refuse dev JWT_SECRET/ENCRYPTION_KEY outside dev/test (PMS-499)
a37c2bfMerge pull request 'chore(toolchain): pin rust-toolchain.toml to 1.94.1 (PMS-412)' (#377) from chore/PMS-412-pin-rust-toolchain into main
8262fb9chore(toolchain): pin rust-toolchain.toml to 1.94.1 (PMS-412)
0952d0fMerge pull request 'feat(assets): add licence section (vendor, seat count, expiry) to CMDB (PMS-454)' (#376) from feat/PMS-454-asset-license-fields into main
c3b4f31feat(assets): add licence section (vendor, seat count, expiry) to CMDB (PMS-454)
df9ea35Merge pull request 'chore(ci): rename OCI build job to mokosh-server (PMS-133)' (#374) from chore/PMS-133-rename-oci-job-to-mokosh-server into main
71932eechore(ci): rename OCI build job to mokosh-server (PMS-133)
ee465acMerge pull request 'chore(security): triage audit roll-up findings (PMS-504)' (#373) from chore/PMS-504-security-audit-triage into main
2d4cf75Merge pull request 'ci(oci): switch build cache from type=registry/inline to type=gha' (#366) from fix/PMS-525-oci-gha-build-cache into main
fd0051cMerge branch 'main' into fix/PMS-525-oci-gha-build-cache
6dc0077chore(security): triage audit roll-up findings (PMS-504)
05ff30cMerge pull request 'fix(ci): pass PR head ref as data, scope contents:write to publish job (PMS-500)' (#372) from fix/PMS-500-harden-create-release-injection into main
7cdf124fix(ci): pass PR head ref as data, scope contents:write to publish job (PMS-500)
821b04aMerge pull request 'feat(dev): merge compose.dev-sso overlay into compose.dev.yml (PMS-511)' (#371) from feat/PMS-511-merge-dev-compose-files into main
4dd9fdbfeat(dev): merge compose.dev-sso overlay into compose.dev.yml (PMS-511)
e6089c9fix(config): refuse to boot with a dev-default JWT_SECRET outside dev/test (PMS-497)
922d736Merge pull request 'feat(cli): fold bootstrap-infisical/clients/qa subcommands into mokosh-server (PMS-494)' (#369) from feat/PMS-494-fold-bootstrap-subcommands-into-server into main
bf8a0d6feat(cli): fold bootstrap-infisical/clients/qa subcommands into mokosh-server (PMS-494)
ac94aaaMerge pull request 'feat(auth): stamp profile_completed_at on Bunyip OIDC INSERT when both name claims arrive (MAPPS-329)' (#368) from feat/MAPPS-329-auto-populate-profile-from-bunyip into main
1a2e641feat(auth): stamp profile_completed_at on Bunyip OIDC INSERT when both name claims arrive (MAPPS-329)
dc6a8bafeat(api): emit security response headers on every response (PMS-388)
f3b1d12ci(oci): switch build cache from type=registry/inline to type=gha
7272270Merge pull request 'test(e2e): un-fixme form-validation + auth-ui to verify AC7 on staging (PMS-519)' (#364) from test/PMS-519-unfixme-form-validation into main
3444532Merge pull request 'fix(e2e): handle the OIDC consent screen in loginViaSpa (PMS-521)' (#365) from fix/PMS-521-loginviaspa-consent into main
bd21d6dtest(e2e): target the visible desktop sidebar, not the hidden drawer (PMS-519)
3d0320etest(e2e): drive form-validation via in-app nav, not hard goto (PMS-519)
b222ff4test(e2e): instrument form-validation + isolate from auth-ui (PMS-519)
356a9ceMerge branch 'fix/PMS-521-loginviaspa-consent' into test/PMS-519-unfixme-form-validation
25c1ea3fix(e2e): handle the OIDC consent screen in loginViaSpa (PMS-521)
44d7796test(e2e): un-fixme form-validation + auth-ui login to verify on staging (PMS-519)
37f3fa9Merge pull request 'test(e2e): form-validation regression coverage (PMS-518 AC7)' (#363) from test/PMS-518-form-validation-e2e into main
98378e6test(e2e): fix form-validation spec quarantine + login frugality (review)
729257ftest(e2e): add form-validation regression coverage (PMS-518 AC7)
bc51006Merge pull request 'fix(timesheets): request full page in history range test (PMS-507)' (#361) from fix/PMS-507-timesheet-history-range into main
b4403d2Merge origin/main into fix/PMS-507-timesheet-history-range
aab6a71Merge pull request 'fix(tickets): honour contact_id filter on list_tickets (MAPPS-311)' (#362) from fix/MAPPS-311-tickets-contact-id-filter into main
248c1b0fix(tickets): honour contact_id filter on list_tickets (MAPPS-311)
771ca07Merge pull request 'feat(attachments): ticket-note attachment upload / download / delete (PMS-483)' (#358) from feat/PMS-483-note-attachments into main
a7d2f6dfix(attachments): portal sub-router needs its own auth middleware layer (PMS-483)
a5619c6fix(test): portal login body must include tenant_slug (PMS-483)
e9443dcMerge pull request 'feat(timesheets): status filter + multi-week range + decision audit on list (PMS-506)' (#360) from feat/PMS-506-timesheet-history into main
43583f1fix(timesheets): request full page in history range test (PMS-507)
4ae0471fix(test): seed contact uses is_portal_user, not portal_enabled (PMS-483)
3227ab4fix(test): timesheet_history fixture must spell out pagination (PMS-506)
4451660fix(test): seed distinctly-named companies in portal cross-company test (PMS-483)
60b7fe5feat(timesheets): status filter + multi-week range + decision audit on list (PMS-506)
b99e0baMerge pull request 'feat(approvals): change_requests + quotes parent tables (PMS-484)' (#357) from feat/PMS-484-approvals-parent-tables into main
46f0ea9Merge pull request 'feat(kb): top-ticket-driving-articles endpoint (PMS-485)' (#356) from feat/PMS-485-kb-top-driving into main
5c0ad78feat(attachments): ticket-note attachment upload / download / delete (PMS-483)
d54fec4feat(approvals): change_requests + quotes parent tables (PMS-484)
79300a1feat(kb): top-ticket-driving-articles endpoint (PMS-485)
c500b82Merge pull request 'docs(e2e): add dev-docs/e2e.md engineering reference' (#355) from docs/PMS-492-e2e-kb into main
df31fd6docs(e2e): add dev-docs/e2e.md engineering reference
7d24578Merge pull request 'docs: add postgres provisioning + RLS conversation transcription' (#354) from docs/postgres-security-transcription into main
46f4358docs: add postgres provisioning + RLS conversation transcription
3713f71 Merge pull request 'chore(dev): move RLS bootstrap to postgres initdb.d, drop password-drift reset' (#353) from chore/PMS-488-postgres-initdb-rls into main
c55ae98chore(dev): move RLS bootstrap to postgres initdb.d, drop password-drift reset
3bcd7dbMerge pull request 'refactor: collapse CreateTicketRequest + RequireAdminUser + CurrentContact::tenant (PMS-479)' (#352) from feat/PMS-479-refactor-boilerplate into main
13ca35drefactor: collapse CreateTicketRequest + RequireAdminUser + CurrentContact::tenant (PMS-479)
81bbfb6Merge pull request 'feat(dashboards): scheduled dashboard delivery worker (PMS-471)' (#349) from feat/PMS-471-scheduled-dashboards into main
bbebe35Merge pull request 'feat(approvals): polymorphic approval surface across tickets + time-entries (PMS-470)' (#351) from feat/PMS-470-polymorphic-approvals into main
607979bMerge pull request 'feat(notes): expose created_by_contact_id on note DTO + contact-notes feed (PMS-468)' (#350) from feat/PMS-468-portal-notes-attachments into main
94f4d1efeat(approvals): polymorphic approval surface across tickets + time-entries (PMS-470)
371c12afeat(dashboards): scheduled dashboard delivery worker (PMS-471)
9a48f58feat(notes): expose created_by_contact_id on note DTO + contact-notes feed (PMS-468)
2ceb931Merge pull request 'feat(workflows): mutating actions on transition triggers + per-tenant cycle cap (PMS-467)' (#345) from feat/PMS-467-workflow-mutating-transitions into main
74e08a0feat(workflows): mutating actions on transition triggers + per-tenant cycle cap (PMS-467)
f89a41bMerge pull request 'feat(reports): scheduled report delivery worker (PMS-478)' (#348) from feat/PMS-478-scheduled-reports into main
c14ca8eMerge pull request 'feat(assets): CI impact-graph traversal endpoint (PMS-475)' (#347) from feat/PMS-475-ci-impact-traversal into main
1cbc846feat(reports): scheduled report delivery worker (PMS-478)
5cc093efeat(assets): CI impact-graph traversal endpoint (PMS-475)
41fbfefMerge pull request 'feat(email-intake): auto-create contact + reply-as-comment + intake-log audit (PMS-469)' (#346) from feat/PMS-469-email-intake-follow-ups into main
660e4d7feat(email-intake): auto-create contact + reply-as-comment + intake-log audit (PMS-469)
7a9b4daMerge pull request 'feat(reports): saved-report execution runtime - tickets, equality+IN, whitelisted columns (PMS-477)' (#344) from feat/PMS-477-report-execution into main
b81787afeat(reports): saved-report execution runtime - tickets, equality+IN, whitelisted columns (PMS-477)
d32fd2aMerge pull request 'feat(workflows): ticket.status_changed + ticket.priority_changed triggers (PMS-448 phase 2)' (#343) from feat/PMS-448-phase2-more-triggers into main
0638a98Merge pull request 'feat(email-intake): admin CRUD for tenant intake tokens (PMS-450 phase 2)' (#342) from feat/PMS-450-phase2-token-admin into main
5b0dcb9Merge pull request 'feat(workflows): ticket.created workflow rules with in-line executor (PMS-448 phase 1)' (#341) from feat/PMS-448-ticket-created-rules into main
9d28927feat(workflows): ticket.status_changed + ticket.priority_changed triggers (PMS-448 phase 2)
0b55f25feat(email-intake): admin CRUD for tenant intake tokens (PMS-450 phase 2)
8b499a6Merge pull request 'feat(approvals): per-ticket approval requests (PMS-451 phase 1)' (#334) from feat/PMS-451-ticket-approvals into main
5f2f6bfMerge pull request 'feat(portal): customer ticket comments (PMS-449 phase 1)' (#339) from feat/PMS-449-portal-ticket-comments into main
1a17f43fix(approvals): use axum 0.8 brace path-capture syntax (PMS-451)
eb6a6ebfeat(approvals): per-ticket approval requests (PMS-451 phase 1)
7f28f34feat(workflows): ticket.created workflow rules with in-line executor (PMS-448 phase 1)
746efc2Merge pull request 'feat(reports): saved custom-report definitions (PMS-457 phase 1)' (#340) from feat/PMS-457-saved-reports into main
6706fa6feat(reports): saved custom-report definitions (PMS-457 phase 1)
5811441Merge pull request 'feat(cmdb): ITIL CI classification on asset types and lifecycle on assets (PMS-456)' (#336) from feat/PMS-456-itil-ci-types into main
642f84cMerge pull request 'feat(email-intake): tenant-scoped email-to-ticket POST endpoint (PMS-450 phase 1)' (#337) from feat/PMS-450-email-intake into main
f655561feat(portal): customer ticket comments (PMS-449 phase 1)
5071ad9feat(email-intake): tenant-scoped email-to-ticket POST endpoint (PMS-450 phase 1)
9154572Merge pull request 'feat(tickets): source KB article on ticket creation (PMS-452 phase 1)' (#338) from feat/PMS-452-kb-source-ticket into main
2b9f90cfeat(tickets): source KB article on ticket creation (PMS-452 phase 1)
d25ebcafeat(cmdb): ITIL CI classification on asset types and lifecycle on assets (PMS-456)
17f9154Merge pull request 'feat/PMS-453-saved-dashboards' (#335) from feat/PMS-453-saved-dashboards into main
99fb6affix(dashboards): use axum 0.8 brace path-capture syntax (PMS-453)
8959ddffeat(dashboards): per-user saved dashboards CRUD (PMS-453 phase 1)
6691ce8feat(assets): CMDB expansion - assigned user, IP, hostname, MAC, installed date, department, in-transit ticket (PMS-454)
bcaa2a8Merge pull request 'feat(audit): tenant-scoped CSV export endpoint (PMS-455)' (#333) from feat/PMS-455-audit-log-csv-export into main
987b273Merge pull request 'feat(search): cross-entity tenant-scoped /api/v1/search endpoint (MAPPS-298)' (#332) from feat/MAPPS-298-global-search-endpoint into main
a6f764efeat(audit): tenant-scoped CSV export endpoint (PMS-455)
7c04a3bfeat(search): cross-entity tenant-scoped /api/v1/search endpoint (MAPPS-298)
0aa200bMerge pull request 'fix(auth): preserve invite role over the Bunyip subscriber floor' (#324) from fix/PMS-458-preserve-invite-role-over-subscriber-floor into main
0843268Merge origin/main into fix/PMS-458-preserve-invite-role-over-subscriber-floor
b6ce330Merge pull request 'test(contacts): isolate duplicate-name assertion from demo seed' (#331) from fix/PMS-464-company-dup-test-demo-seed into main
22ad97fMerge branch 'main' into fix/PMS-464-company-dup-test-demo-seed
ea44c80Merge pull request 'ci(e2e): run npm/npx via corepack, not the absent npm24' (#330) from fix/PMS-462-e2e-corepack-npm into main
5afc32btest(contacts): isolate duplicate-name assertion from demo seed
8258de5ci(e2e): run npm/npx via corepack, not the absent npm24
7f258aaMerge branch 'main' into fix/PMS-429-e2e-versioned-node-binaries
ff4c49aMerge pull request 'chore: Claude fix is now Claude Run' (#329) from chore/remove-claude-fix into main
8710667chore: Claude fix is now Claude Run
04c86a9Merge pull request 'chore: Sync the checks and justfile recipes' (#328) from chore/sync-checks-justfile into main
0f2909fMerge branch 'main' into chore/sync-checks-justfile
ecf3745chore: Sync the checks and justfile recipes
3718d2fMerge pull request 'feat(jit): consume bunyip given_name/family_name claims (BUNYIP-141)' (#327) from feat/bunyip-141-jit-consume-name-claims into main
4ebd699Merge pull request 'fix(ci): create-release workflow concludes success on non-release merges' (#326) from fix/ci-create-release-skip-conclusion into main
4d03d85fix(ci): create-release workflow concludes success on non-release merges
a31a5b7Merge pull request 'fix(auth): gate PMS-447 subscriber-Admin floor on invite absence' (#325) from fix/PMS-447-preserve-invite-role into main
1e0efe3fix(auth): gate PMS-447 subscriber-Admin floor on invite absence
83bf97efix(auth): preserve invite role over the Bunyip subscriber floor
ecaf31eMerge pull request 'feat(auth): single-tenancy admin floor on Bunyip RS path (PMS-447)' (#323) from feat/PMS-447-single-tenancy-admin-default into main
8802de2feat(auth): single-tenancy admin floor on Bunyip RS path (PMS-447)
7a21cc2Merge branch 'main' into fix/PMS-429-e2e-versioned-node-binaries
c58b00dMerge pull request 'test(e2e): quarantine OIDC token-flow spec blocked on bunyip BUNYIP-146' (#319) from fix/PMS-435-quarantine-oidc-token-flow-bunyip-146 into main
c684ed6Merge remote-tracking branch 'origin/main' into fix/PMS-435-quarantine-oidc-token-flow-bunyip-146
1f57c76Merge pull request 'test(e2e): surface authorize redirect target in OIDC token-flow (PMS-443)' (#322) from chore/pms-e2e-oidc-surface-redirect-target into main
81c162btest(e2e): surface authorize redirect target in OIDC token-flow
e3bf9b6Merge pull request 'fix(rls): make tenant-isolation GUC count symmetric with owner count' (#320) from fix/PMS-437-rls-isolation-internal-count-symmetry into main
6103ab7fix(rls): make tenant-isolation GUC count symmetric with owner count
1a2b2ddtest(e2e): quarantine OIDC token-flow spec blocked on bunyip BUNYIP-146
87e6fb8Merge pull request 'chore(e2e): log OP-session cookie name to diagnose OIDC authorize bounce (PMS-434)' (#318) from chore/pms-e2e-oidc-cookie-name-diagnostic into main
0962f69chore(e2e): log OP-session cookie name to diagnose OIDC authorize bounce
ec767bcci(e2e): invoke versioned node24/npm24/npx24 binaries
6b2b286ci(e2e): use runner's preinstalled nodejs24 instead of setup-node
74602d6Merge pull request 'test(rls): make tenant-isolation count robust to own-company seed' (#310) from fix/PMS-414-rls-isolation-test-own-company-seed into main
9625d65Merge branch 'main' into fix/PMS-414-rls-isolation-test-own-company-seed
dafee52Merge pull request 'feat(ci): cap native check.yml parallelism at nproc/2' (#313) from feat/GOV-10-native-check-nproc-cap into main
3f7e38dfeat(ci): cap native check.yml + integration.yml parallelism at nproc/2
3616ce4feat(jit): consume bunyip given_name/family_name claims (BUNYIP-141)
4271f34Merge pull request 'fix(migrations): exempt internal own-company from duplicate-name unique index (staging hotfix, PMS-413)' (#311) from fix/PMS-413-own-company-name-unique-collision into main
31132b3fix(migrations): exempt internal own-company from the duplicate-name unique index (PMS-413)
f84b10cMerge branch 'main' into fix/PMS-414-rls-isolation-test-own-company-seed
d7f575aMerge pull request 'feat(tenants): tenant own-company for general time logging (PMS-413)' (#309) from feat/PMS-413-tenant-own-company into main
45ecbb7style: match CI rustfmt for the PMS-413 emptiness-check edits (PMS-413)
edbd8cdfix(seed): exclude internal own-company from tenant emptiness checks (PMS-413)
1cce469test(rls): make tenant-isolation count robust to own-company seed
b3e1632fix(reports): exclude internal own-company from clients report; match CI rustfmt (PMS-413)
cf0a808feat(tenants): add tenant own-company for general time logging
42744d5Merge pull request 'Seed pre-commit .env from committed .env.example' (#302) from fix/pre-commit-clean-clone into main
ff6111bMerge branch 'main' into fix/pre-commit-clean-clone
73692c6Merge pull request 'feat(contracts): add weekly and bi-weekly billing cycles (PMS-404)' (#308) from feat/PMS-404-weekly-biweekly-billing-cycles into main
4a1826fMerge pull request 'fix(time-tracking): consume contract hours on timesheet approval (PMS-405)' (#307) from fix/PMS-405-wire-time-to-contract-balance into main
775efeaMerge pull request 'feat(projects): reject task/phase create on cancelled project (PMS-399)' (#305) from fix/PMS-399-reject-children-on-cancelled-project into main
af44724style: match CI rustfmt in PMS-404 contracts tests (PMS-404)
ea42a18style: match CI rustfmt in contracts tests (PMS-405)
224c2b7style: collapse short query to one line for CI rustfmt (PMS-399)
bc71b9cfeat(projects): reject task/phase create on cancelled project (PMS-399)
7f0cb05feat(contracts): add weekly and bi_weekly billing cycles
ff194eeMerge pull request 'feat(contacts): freeform company on contacts (nullable company_id + company_name) (PMS-402)' (#306) from feat/PMS-402-freeform-company-on-contacts into main
9926b2efix(time): consume contract hours on timesheet approval
4c29f2efeat(contacts): accept freeform company on contacts
7d74781Merge pull request 'fix(projects): reject inverted task start/due dates (PMS-398)' (#304) from fix/PMS-398-task-date-ordering into main
7828b27fix(projects): reject inverted task start/due dates (PMS-398)
712cb34Merge pull request 'feat(time-tracking): enforce per-tenant max-hours-per-day cap' (#298) from feat/PMS-396-max-hours-per-day-cap into main
9993537fix(test): set work_category on day-cap test helpers after rebase
e0ecc09Merge pull request 'test(tickets): pin server-side inline status/priority/assignee edit + SLA recalc' (#272) from test/pms-359-ticket-inline-edits into main
2503606test(tickets): pin server-side inline status/priority/assignee edit + SLA recalc
cc2b1deMerge pull request 'feat(projects): per-project standard due date override (PMS-345)' (#268) from feat/PMS-345-per-project-default-due into main
15abfafMerge pull request 'feat(calendar): add scheduling-template model and CRUD endpoints (PMS-403)' (#299) from feat/PMS-403-scheduling-templates into main
4653c86Merge pull request 'feat(tickets): wire team_id filter and team-scoped dashboard query' (#295) from feat/PMS-406-ticket-team-scope-filter into main
4c0296bMerge pull request 'feat(contacts): reject duplicate company names per tenant' (#296) from feat/PMS-400-reject-duplicate-company-names into main
69e707aMerge pull request 'test(modules): verify company-scoped list endpoint filtering' (#300) from test/PMS-401-company-scoped-list-filtering into main
0315de4fix(seed): set default_due_business_days on QA project specs after rebase
e0636e2chore(migrations): renumber project_default_due_business_days 051->059 after PMS-411 collision fix
e8d995cfeat(projects): per-project standard due date override (PMS-345)
43cf626feat(time-tracking): enforce per-tenant max-hours-per-day cap
90e3717chore(migrations): renumber tickets_tenant_team_idx to 058 after PMS-411 collision fix
11fafc0chore(migrations): renumber companies_tenant_name_unique to 057 after PMS-411 collision fix
73ef7b0feat(tickets): wire team_id filter and team-scoped dashboard query
4e5ebbdfeat(contacts): reject duplicate company names per tenant
335773echore(migrations): renumber scheduling_templates 054->056 after PMS-411 collision fix
c8114e3feat(calendar): add scheduling-template model and CRUD endpoints (PMS-403)
aa720ffMerge pull request 'fix(migrations): renumber duplicate 054 prefix to 055 (PMS-411)' (#303) from fix/PMS-migration-054-prefix-collision into main
57aefe6fix(migrations): renumber duplicate 054 prefix to 055 (PMS-411)
3af2a24fix(hooks): seed .env from committed .env.example on clean clone
dfa58e9Merge pull request 'style(time-tracking): rustfmt the work_category unit tests' (#297) from feat/PMS-394-time-entry-general-category into main
07abad8Merge pull request 'feat(auth): persist per-user theme preference (base mode + accent) (PMS-410)' (#301) from fix/PMS-410-theme-prefs into main
c355277feat(auth): persist per-user theme preference (base mode + accent) (PMS-410)
9d6b083test(modules): verify company-scoped list endpoint filtering
1e82dedstyle(time-tracking): rustfmt the work_category unit tests
9c87f15feat(time-tracking): add general-bucket work_category to time entries
a5b45baMerge pull request 'fix(validation): range/scale-guard money and hours numeric fields (PMS-383)' (#294) from fix/PMS-383-numeric-money-hours-validation into main
80a0333Merge branch 'main' into fix/PMS-383-numeric-money-hours-validation
d372b9bMerge pull request 'feat(notifications): add PUT update endpoints for channels/templates/rules' (#293) from feat/PMS-386-notification-config-update-endpoints into main
f5756b2Merge branch 'main' into feat/PMS-386-notification-config-update-endpoints
91a42cdMerge pull request 'feat(rmm): add PUT update routes for device-mappings and alert-rules' (#292) from feat/PMS-387-rmm-device-mapping-alert-rule-update into main
42acff8Merge branch 'main' into feat/PMS-387-rmm-device-mapping-alert-rule-update
d08de8fMerge pull request 'fix(reports): bucket dashboard ticket trend in the user's timezone' (#274) from fix/pms-360-user-timezone-date-bucketing into main
c3814e3Merge branch 'main' into fix/pms-360-user-timezone-date-bucketing
6eef45efix(validation): range/scale-guard money and hours numeric fields (PMS-383)
cad860afeat(notifications): add PUT update endpoints for channels/templates/rules
ada540cfeat(rmm): add PUT update routes for device-mappings and alert-rules
9d61aa5Merge pull request 'fix(validation): validate tenant admin_email as an email (PMS-385)' (#290) from fix/PMS-385-tenant-admin-email-validation into main
c86c58dMerge branch 'main' into fix/PMS-385-tenant-admin-email-validation
fc42816Merge pull request 'fix(validation): reject non-positive time-entry duration_minutes (PMS-384)' (#291) from fix/PMS-384-time-entry-duration-validation into main
f7366bfMerge branch 'main' into fix/PMS-384-time-entry-duration-validation
a432921Merge pull request 'fix(cors): cache preflight with Access-Control-Max-Age=600 (PMS-389)' (#289) from fix/PMS-389-cors-max-age into main
87598dafix(validation): reject non-positive time-entry duration_minutes
5917e76fix(validation): validate tenant admin_email as an email
f200bd3fix(cors): cache preflight with Access-Control-Max-Age=600
50ea5ccMerge pull request 'fix(seed): repair qa seed so main compiles (actual_end_date + AuditCtx) (PMS-379)' (#288) from fix/qa-seed-build-actual-end-date-audit-ctx into main
2bc8995fix(migrations): renumber duplicate 051 prefixes to 052/053
5869e1ffix(seed): repair qa seed for actual_end_date + AuditCtx create signatures
0b3dd22Merge main into fix/pms-360-user-timezone-date-bucketing
d6d16dfMerge pull request 'test(projects): pin oversized-budget 422 and company-id injection safety' (#283) from fix/pms-316-project-budget-oversize-and-safe-company-tests into main
0a4a1b0Merge pull request 'fix(validation): recurse nested ValidationErrors so 422 errors[] carry dotted field paths' (#280) from fix/pms-330-nested-validation-field-paths into main
13ddfabMerge pull request 'test(contacts): pin company search to substring ILIKE, not leading prefix' (#279) from fix/pms-372-company-search-substring into main
a9b0c7eMerge pull request 'fix(contacts): populate company_name via LEFT JOIN to companies' (#266) from fix/pms-334-contact-company-name into main
5799c34Merge pull request 'fix(billing): widen tax_rates.rate and validate the percentage range' (#281) from fix/pms-339-tax-rate-column-width-and-validation into main
20307fbMerge pull request 'feat(projects): accept actual_end_date on create for edit-form parity' (#278) from feat/pms-361-create-project-symmetry into main
ae60fa7Merge pull request 'feat(projects): surface owning company name in ProjectResponse' (#276) from feat/pms-335-project-company-name into main
7a3f773Merge pull request 'fix(assets): surface company_name on AssetResponse via LEFT JOIN' (#275) from fix/pms-336-asset-company-name into main
dfa96c8Merge pull request 'fix(billing): reject non-positive payment amounts with a 422' (#269) from fix/PMS-373-reject-non-positive-payment-amount into main
62433cbMerge pull request 'fix(tickets): humanise FK column names in change-history field labels' (#267) from fix/pms-370-humanize-history-field-labels into main
8c74d8bMerge pull request 'feat(seed): on-demand QA walkthrough dataset for a QA-marked tenant' (#265) from feat/PMS-331-qa-seed-dataset into main
d24677eMerge pull request 'fix(billing): make payment-gateway credential a write-only secret' (#263) from fix/pms-342-payment-gateway-write-only-secret into main
6730ed2Merge pull request 'feat(knowledge_base): wire client_specific company scoping write path' (#260) from feat/pms-341-kb-company-ids into main
077fce3Merge pull request 'test(tickets): pin priority round-trip on ticket create (PMS-358)' (#270) from feat/pms-358-priority-roundtrip-integration-test into main
45c0c07Merge pull request 'fix(validation): symmetric URL error message + close credential URL gap (PMS-351)' (#273) from fix/pms-351-url-field-validation-sweep into main
3504d3cMerge pull request 'fix(rbac): gate Contracts/Rate Cards reads and financial reports like Invoices' (#271) from fix/PMS-350-rbac-finance-gates into main
d12dbbafix(rbac): gate Client Profitability report + its CSV export like Invoices
3b7c2bdMerge pull request 'feat(audit): emit Create audit row on mileage entry creation' (#284) from feat/pms-315-mileage-create-audit into main
5f0f3e1feat(audit): emit Create audit row on mileage entry creation
b8ea044Merge pull request 'fix(projects): emit Create audit row on task creation' (#282) from fix/pms-318-create-task-audit-row into main
2a173e4feat(audit): emit Create audit rows for every remaining create path
1bb9439Merge pull request 'feat(mileage): mileage entries, per-mile rate card rate, invoice line type' (#277) from feat/pms-315-mileage-entries into main
0cd6088fix(mileage,time): validate re-associated ticket_id on update against tenant
3fd861eMerge pull request 'fix(calendar): validate recurrence_rule as RFC 5545 on appointment create' (#264) from fix/pms-374-validate-recurrence-rule into main
4ad95d0Merge pull request 'fix(reports): zero-fill canonical project and asset status buckets' (#261) from fix/pms-366-project-status-counters-zero-fill into main
7b2370dtest(projects): pin oversized-budget 422 and company-id injection safety
649c820fix(projects): emit Create audit row on task creation
e70560cfix(billing): widen tax_rates.rate and validate the percentage range
29c12e3fix(validation): recurse nested ValidationErrors so 422 errors[] carry dotted field paths
6a16cf2test(contacts): pin company search to substring ILIKE, not leading prefix
5ac383afeat(projects): accept actual_end_date on create for edit-form parity
ee415e8feat(mileage): mileage entries, per-mile rate card rate, invoice line type
43102d3feat(projects): surface owning company name in ProjectResponse
a3c9bb3fix(assets): surface company_name on AssetResponse via LEFT JOIN
e56be90fix(reports): bucket dashboard ticket trend in the user's timezone
8689abbfix(validation): symmetric URL error message + close credential URL gap (PMS-351)
a12a3b8Merge pull request 'fix(validation): re-key cross-field rules onto a named field so forms show inline messages' (#262) from fix/pms-364-cross-field-validation-field-key into main
73cc9affix(rbac): gate Contracts/Rate Cards reads and financial reports like Invoices
075555dtest(tickets): pin priority round-trip on ticket create (PMS-358)
ca16ea9fix(billing): reject non-positive payment amounts with a 422
a7565fefix(tickets): humanise FK column names in change-history field labels
27ddca3fix(contacts): populate company_name via LEFT JOIN to companies
553a995feat(seed): on-demand QA walkthrough dataset for a QA-marked tenant
7e04bbcfix(calendar): validate recurrence_rule as RFC 5545 on appointment create
8d31b36fix(billing): make payment-gateway credential a write-only secret
064c8dffix(validation): re-key cross-field rules onto a named field so forms show inline messages
13b7252fix(reports): zero-fill canonical project and asset status buckets
82a6912feat(knowledge_base): wire client_specific company scoping write path
1cb2ab1Merge pull request 'fix(tickets,assets): asset_id update + AssetFilter.q so PMS-344 inline editor and picker work end to end' (#259) from fix/pms-344-asset-filter-and-update-clearing-semantics into main
fb4e7dcfix(tickets,assets): asset_id update + AssetFilter.q so PMS-344 inline editor and picker work end to end
1e8b387Merge pull request 'feat(tickets): TicketResponse carries asset_id + asset_name; TicketFilter accepts asset_id (PMS-344)' (#258) from feat/pms-344-server-asset-id-filter-and-name into main
3a35f97feat(tickets): TicketResponse carries asset_id + asset_name; TicketFilter accepts asset_id (PMS-344)
c9f84e0Merge pull request 'feat(scheduling): tenant-wide standard due date for tasks and no-SLA tickets' (#257) from feat/PMS-345-standard-due-date into main
12f9bb7feat(scheduling): tenant-wide standard due date for tasks and no-SLA tickets
c3fa665Merge pull request 'fix(audit): skip change-history entry for description checkbox toggles (PMS-349)' (#256) from fix/PMS-349-skip-audit-for-checkbox-toggles into main
d793cbafix(audit): don't record a change-history entry for description checkbox toggles (PMS-349)
0b6287dMerge pull request 'fix(sla): validate SLA target hours (non-negative, <=2dp, first_response<=resolution) (PMS-338)' (#255) from fix/PMS-338-sla-target-validation into main
87494f2Merge remote-tracking branch 'origin/main' into fix/PMS-338-sla-target-validation
2957572Merge pull request 'fix(contracts): validate billing_cycle and status at the request layer (422 not 500) (PMS-337)' (#254) from fix/PMS-337-contract-status-billing-validation into main
1cf5505fix(sla): validate SLA target hours (non-negative, <=2dp, first_response<=resolution)
6d378c9fix(contracts): validate billing_cycle and status at the request layer (422 not 500)
c1ed191Merge pull request 'fix(calendar): reject inverted appointment time range on update (PMS-343)' (#253) from fix/PMS-343-appointment-time-range into main
d3be695fix(calendar): reject inverted appointment time range on update (PMS-343)
9f1f092Merge pull request 'feat(billing): payment_terms lookup table + CRUD, invoices reference it by FK' (#252) from feat/PMS-333-payment-terms-lookup into main
8e9d65bfeat(billing): payment_terms lookup table + CRUD, invoices reference it by FK
6de032aMerge pull request 'fix(dev): pre-create pg extensions + grant CREATE-on-db for fresh split-role volume' (#251) from fix/dev-pg-preinstall-extensions into main
32d1b38fix(dev): pre-create pg extensions + grant CREATE-on-db for fresh split-role volume
e866ed1Merge pull request 'feat(time): join work-item names (ticket/project/task) into the time-entry response' (#250) from feat/PMS-332-time-entry-work-item-names into main
1e22e9cfeat(time): join work-item names into the time-entry response
6982cadMerge pull request 'feat(projects): expose per-task logged_hours (non-rejected) alongside approved actual_hours' (#249) from feat/PMS-329-task-logged-hours into main
ecd62b4feat(projects): expose per-task logged_hours alongside approved actual_hours
b9769f2Merge pull request 'fix(time): PUT /time-entries preserves task_id (and expose it in the response)' (#248) from fix/PMS-328-time-entry-preserve-task-id into main
319b96efix(time): restrict time-entry edit/delete to owner or admin
106c298fix(time): preserve task_id on time-entry update and expose it
828afbfMerge pull request 'docs(qa): extend QA test-plan prompt with this round's validation findings [PMS-326]' (#246) from docs/PMS-326-qa-test-plan into main
e2c60acMerge pull request 'feat(contacts): validate phone/timezone/country/postal (fix contact phone 500) [PMS-325]' (#247) from fix/PMS-325-contact-field-validation into main
90cefedfeat(contacts): validate phone, timezone, country, and postal fields
b13bfbddocs(qa): fold validation findings into the QA test-plan prompt
768412dMerge pull request 'fix(projects): server-side validation for name + budget (fix Budget Hours 422) [PMS-324]' (#243) from fix/PMS-324-project-input-validation into main
457be7fMerge branch 'main' into fix/PMS-324-project-input-validation
0c46c90Merge pull request 'feat(contracts): add GET /rate-cards/{id} for single rate-card fetch' (#244) from feat/PMS-327-get-rate-card into main
2807521feat(contracts): add GET /rate-cards/{id} for single rate-card fetch
39de4e6Merge pull request 'harden(lookups): DB partial unique index for single-default per tenant' (#242) from feat/PMS-323-single-default-unique-index into main
0953a74fix(projects): validate name length and budget fields, accept numeric budgets
fd15023harden(lookups): DB partial unique index for single-default per tenant
1e649e9Merge pull request 'test(projects): pin duplicate project-type name as a 409' (#241) from feat/PMS-322-project-type-lookup into main
9bdca67test(projects): pin duplicate project-type name as a 409
aa04df8Merge pull request 'feat(projects): tenant-scoped project_types lookup table + CRUD' (#240) from feat/PMS-322-project-type-lookup into main
77625cafeat(projects): tenant-scoped project_types lookup + CRUD
c4dabdcMerge pull request 'feat(tickets): management CRUD for ticket status/priority/type/queue/category lookups' (#239) from feat/PMS-321-ticket-lookup-crud into main
d6c7f17fix(tickets): enforce same-tenant category parent at the DB layer (migration 047)
e7ec4a1fix(tickets): reject transitive category cycles; cover priority sla_multiplier
06bbe5cfeat(tickets): management CRUD for status/priority/type/queue/category lookups
8a8253fMerge pull request 'fix(justfile): add ensure-env dependency to dev-clean' (#238) from fix/PMS-307-dev-clean-ensure-env into main
7438c7ffix(justfile): add ensure-env dependency to dev-cleanDownloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
Source code (ZIP)