Let an event invite its guests, and put it on their calendar
Saving an event told nobody. The guest list was materialized and the audience stored, and the people on it heard nothing until a reminder fired — which reaches ...
A three-year deal totals three years, not one month of it
Two faults, both showing a monthly figure where the term's value belonged. 1. The headline took periodTotal + setup. On a MONTHLY option committed to 36 mon...
The check constraint a fourth visibility would break
Hibernate wrote `check (visibility in **************** 'PLATFORM_ADMIN_ONLY'))` when it created report_catalog. ddl-auto adds columns and never rewrites a const...
Let the platform decide who may see each report
MANAGE_REPORTS, appended to PlatformRightType, and a REPORT_CATALOG override row per report holding one of ALL_ORGS, PLATFORM_ORG_ONLY or PLATFORM_ADMIN_ONLY. ...
Bill the whole term up front, and say so on the quote
An org that charges up front saw the monthly rate on a three-year deal. The setting deciding that already existed — **************** — but it reached only Quote...
The one-time setup fee belongs in the quote's total
A setup fee typed on an option reached exactly one figure — QuoteOptionTotals put it in contractTotal — and applyOptionHeadlineTotals then built the quote's hea...
The email a scheduled report arrives in
REPORT_SCHEDULED, registered in CANONICAL_KEYS — absent from that list a template is a permanent 404, whatever files exist beside it. The body states the data ...
A service-work report, and a share target that fits every id
ServiceWorkReport is the tenth seed report and the one that makes row-level scope real rather than merely present. Commerce carries the platform's own/all pair ...
ReportDefinition never shipped the narrower rights its resolver reads
ReportScopeResolver, its test and this class's own javadoc all name alsoGrantedBy, and ReportSecurityScope has had SELF/TEAM/ORGANIZATION since the framework la...
The Report Studio framework, and nine reports built on it
A report is now a Java class here and nothing anywhere else. ReportDefinition describes what a report is, what it may be asked, which columns it has and how eac...
Let an org put a custom status label back to blank
A status label had no way to be removed. The settings screen saved through an upsert-only bulk write, so the only thing a request could say was "this status is ...
Persist a market's quote-contact rule, and refuse a half-stated one
The DTOs carried quoteContactMode and quoteContactMemberId but no writer read them, so the setting round-tripped through the form and was silently dropped. Both...
A market decides who a quote names as the customer's contact
QuoteContactMode gives a LeadMarket three answers: the lead's assigned agent (resolved per read, which is what every quote does today and what a null column mea...
Article-to-article relations
KB_ARTICLE_RELATIONS holds the curated "see also" links between articles in one knowledge base. Rows are per direction and the pair is kept symmetric by KbArtic...
A three-year term, and the promotion rules that were never read
Adds BillingCycle.TRIENNIAL so a subscriber can commit for three years. The column is varchar with no CHECK constraint anywhere, so this needs no migration — bu...
Carry the report title through a Send To AI dispatch
The dispatch sent the operator's instruction and the bug description and nothing else, so the one line saying what the report is ABOUT never reached the session...
A join/leave row has to carry the name of who it is about
The id alone cannot be resolved in the one case these rows exist for. A "removed" or "left" line names somebody who is, by then, no longer in the session, so th...
Declare removedByMemberId, or the relay drops it in silence
The NATS payload for MEMBER_REMOVED carries who did the removing, but the NATS→STOMP relay projects every frame through ChatMessageDto — so a field this class d...
A chat can be named, starred, and have somebody removed from it
Three fields and one method, all of which the chat feature already had the shape for and none of which it could record. MEDIA_SESSION_CHAT gains TITLE. That ta...
The deposit account an organization asks customers to pay into
Six columns on `orgs` and the wire contract for printing them on a quote, so a company that receives one knows where to send the money without telephoning to as...
A domain is claimed by proving it, not by typing it
Three rules, and they only make sense together. **Naming a domain claims nothing.** An FQDN was globally unique here, so the first organization to enter "acme....
A security model says where each member type lands on "/"
Three columns on ChildOrgSecurityModel — DEFAULT_MEMBER_HOME_SCREEN, **************** DEFAULT_ORG_OWNER_HOME_SCREEN. Each holds HOME_SCREEN_DEFAULT or REQUIRES_...
Remove the CREATE_FREE_ORG_WIDGET block with its widget
The Create My Free Org launchpad widget was removed (kamo-internal ab740dd3), so its five rights go with it: CREATE_FREE_ORG_WIDGET (288) and the four policy ch...
Create My Free Org widget rights and Getting Started wizard progress
Adds RoleRightType 288-292 (CREATE_FREE_ORG_WIDGET and its four ADDED/OPTIONAL/ REQUIRED/MOVABLE policy children), hung off CREATE_CHILD_ORG (131). Adds OrgSetu...
Record that Organization.YEAR_EST is optional and may be cleared
The column was always nullable and both server paths already handled null — CreateOrganizationPayloadParser maps an empty or unparseable value to null, and patc...
A security group per app, and the master notes as widgets
Ten new rights, 278-287: NOTES_MASTER_MINE_WIDGET and NOTES_MASTER_OURS_WIDGET, each with the four policy children every home widget carries. Both hang off VIEW...
The credit note, the only correction path for a finalized invoice
B3: Kamo owns everything before finalize() and the provider owns everything after, and every provider on the roadmap treats a finalized invoice as immutable. So...
The document counter, and a number that cannot fork
Every existing document number on this platform is a check-then-insert race with no unique constraint behind it: quote numbers are COUNT(...)+1, subscription in...
The invoice entity, with every tax field and no tax engine
Kamo's own invoice, written only by InvoicingService. Nothing on it is supplied by a caller: every figure is derived from the lines on every write, which is the...
MANAGE_BILLING_PROVIDER (277), a child of commerce settings
Task 8, mirror 1 of 6 (the Java enum) and mirror 2 (the parent(...) line). Id 277 was re-derived from origin/main immediately before allocating it, NOT taken f...
Filter every durable consumer to its own subject
A durable created through NatsMessageService.subscribe carried no filter subject, so it received the WHOLE stream regardless of the subject it was asked for. Th...
Per-viewer read state for system bug reports
SystemBugView is per VIEWER, not per bug — a firstViewedAt column on SystemBug would let whoever opened a report first clear it off every other manager's badge....
The canonical letter a bug reporter gets when their report moves
A member who files a bug or an enhancement had no way to learn what happened to it short of opening the tab and looking. This adds the template that tells them,...
Attribute free extensions to the server they are on
An org running a busy FreePBX server beside a new, empty KamoPBX server saw "21 billable extensions — $63.00 / month" while looking at the KamoPBX one. Both num...
The company phone toggles an individual signature can carry
Two org-wide flags on email_signature_field_config: user_company_phone_main and user_company_phone_toll_free. They put the organization's published line on a me...
The inbound-keyword receipt, and re-key consent by campaign (MS1 Task 3)
Two things the consent ledger needs before an inbound STOP can be recorded tenant-scoped and exactly once. `SmsInboundReceipt` (comms_sms_inbound_receipt) is t...
The sync journal, and a terminal run that really is frozen
BL1 Task 5, shared-library half. Five journal enums, three entities and three repositories under **************** No stereotypes: BillingWormGuard is a plain fi...
E.164 normalizer and SMS keyword interpreter (MS1 Task 1)
Two pure classes with no I/O and no Spring stereotype, so every service can load them and SharedLibBeanSafetyTest stays green. E164.normalize(raw, defaultRegio...
The provider connection row, one per org
BL1 Task 1. A near-verbatim transliteration of the payroll provider enums and PayrollConnection into **************** Enums, one entity and one repository — no ...
The bug-report association holds video too
SYSTEM_BUG_SCREENSHOT now carries screen recordings alongside screenshots. The constant keeps its name and its id — id 17 is written into assoc_id on every row ...
CreateJob, so a work order can be raised without an order
The one verb the service-job surface was missing. Until now the only thing on the platform that could produce a ServiceJob row was **************** off a paid o...
VIEW/MANAGE_ORDERS and VIEW/MANAGE_PRICING, ids 273-276
No order-mutation right existed anywhere. POSController's order endpoints and every pricing and tax handler in CommerceMarketController read the org off the ses...
Publish Patient Records, and make that safe to do
ServiceType.EHR was held at TESTING long after the vertical was finished, because AppCatalogService derives availability from COMPLETED and three separate paths...
A vendor id leaves as a string, for every row
`commerce_vendors.uid` is `INT8 DEFAULT unique_rowid()` -- about 19 digits, where `Number.MAX_SAFE_INTEGER` has sixteen. A numeric id of that size is an IEEE-75...
The per-plan allowance is per seat, and says so
Rename only — PlanStorage.gbPerUser is private to this class and the three call sites are all in it. The comment above it was the misleading half: the allowance...
Line, note, vendor, sign-off and clock writes on a job
SW6b Task 3, library half. Eight new operations on ServiceJobService, plus the wire records for them and the three reads the detail page needs. Three things th...
Job lines, notes and vendors so the work-order tabs can persist
Labour and parts become ServiceJobLine rows on the job rather than ServiceLineItem rows, because OrderLineItem.order is optional = false: a ServiceLineItem cann...
KamoPBX platform settings on SYSTEM_CONFIGURATION
KamoPBX is Kamo's own platform, so all of its configuration is platform-wide: base URL, master account id, account name, admin credential, SIP realm suffix and ...
A line for documents retrieved from other organizations
Its own domain rather than a share of DOCUMENTS, for the reason bulk exports got one: a practice that queries a health information network routinely accumulates...
An org-scoped read/write API for service jobs
ServiceJob has been a mapped entity with repositories and passing tests and no way to read a row. This gives it the header the finished work-order UI already re...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.