Rules derived from BC MCP API page development experience: - api-page-flowfields-must-be-calcfields: FlowFields return empty on API pages unless explicitly CalcFields'd in OnAfterGetRecord - stored-derived-fields-must-not-be-exposed-directly: Stored fields updated only via OnValidate triggers can be stale; recalculate live in OnAfterGetRecord - api-page-key-fields-must-be-editable-on-insert: ODataKeyFields with Editable=false are rejected as unknown properties on POST - api-page-least-privilege-write-access: Create dedicated minimal pages per write concern rather than widening general-purpose pages - agent-must-not-write-business-process-status: Agents must only write developer-tracking fields; business status fields affect invoicing/time registration Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2 KiB
CURABIS MCP: API Pages Must Use Least-Privilege Write Access
Core Principle
A general-purpose API page that exposes many fields should not be widened to allow writes on a single additional field. Instead, create a dedicated minimal API page that exposes only the fields the consumer needs to read and write. This limits the blast radius of any agent or integration mistake.
Why This Matters
An MCP agent operates with the permissions of its service identity, not an individual user. A page that allows writing to many fields gives the agent broad power that is hard to audit and easy to misuse. A dedicated page with one writable field makes the intent explicit and the surface area auditable.
Pattern to Avoid
// WRONG: General page widened with write access to one field
// Now the agent can accidentally (or intentionally) write to all other fields too
field(status; Rec.Status) { } // should be read-only
field(gitHubRepository; Rec."GitHub Repository") { } // the one field we want writable
field(estimatedHours; Rec."Estimated Hours") { } // should be read-only
Correct Pattern
Create a separate, minimal API page:
page 6102904 "CUR MCP Project Repository"
{
// Only two fields: the key and the one writable field
field(no; Rec."No.") { Editable = false; }
field(gitHubRepository; Rec."GitHub Repository") { }
}
Requirements
- Each distinct write concern (e.g., setting a GitHub repo, updating a dev status) should have its own API page or be deliberately grouped only with closely related fields
- Read-only fields on write-enabled pages must carry
Editable = false - The page description must document which fields are writable and why
Verification
For each API page where ModifyAllowed = true (or default), list all fields without Editable = false. Confirm that every writable field is intentionally writable for the same consumer use case. If unrelated fields are writable on the same page, split the page.