Backend and security¶
A Yukon extension is trusted server code inside a tenant site. Every endpoint, job, webhook, migration, credential, and record type is part of that tenant's security boundary.
Depend on the public surface¶
For an extension that requires Yukon, declare
required_apps = ["yukon_crm"]. The supported Python imports are:
Do not import Yukon controllers, internal registries, query implementations, or frontend source. Request a documented contract when the extension needs something the public surface does not expose.
Enforce enablement and permission¶
Enablement stops new extension work; it is not authorization. Every endpoint must still enforce Frappe roles and document permissions.
from __future__ import annotations
import frappe
from yukon_crm.extensions import require_extension_enabled
@frappe.whitelist(methods=["POST"])
def start_sync(record_name: str) -> dict[str, str]:
require_extension_enabled("acme_inventory", default_enabled=False)
frappe.has_permission("Acme Inventory Link", "write", record_name, throw=True)
frappe.enqueue(
"acme_inventory.jobs.sync_record",
queue="short",
enqueue_after_commit=True,
record_name=record_name,
)
return {"status": "Queued"}
Use GET only for idempotent reads, fully annotate the API, validate every
identifier and enum, and return a deliberate payload. Never return raw document
fields, secrets, tracebacks, signatures, or customer data that the caller does
not need.
Protect external boundaries¶
- Store credentials in site configuration, an approved secret manager, or an appropriate encrypted password field. Never return them to the browser.
- Authenticate webhooks, validate replay windows where available, bound request size, and make event processing idempotent.
- Enqueue slow work after the database transaction commits.
- Use bounded timeouts, retries, rate-limit handling, and deterministic deduplication for provider calls.
- Define what disablement does to work already in flight.
- Ship schema and data changes as tested, idempotent Frappe patches.
Every source file must be partner-owned, a declared dependency, or a properly licensed adaptation with required notices preserved.