"""Every field registered as auto-number must be declared with type `autonumber`. The two halves live in separate files and can drift: * `salesforce-crm-standard/autonumber/formats.json` registers the field with the auto-number engine, which generates its values. * `salesforce-crm-standard/objects/standard_objects_spec.json` declares the field's type, and the runtime derives write capability from that type. Only the declaration reaches the capability layer. A field registered as auto-number but declared `string` is generated by the engine yet still advertised as createable/updateable, which makes the record edit form round-trip a value the write path then refuses -- the object becomes un-editable through the UI. That is not hypothetical: `QuoteLineItem.LineNumber` and `OrderItem.OrderItemNumber` drifted this way, and production `_System_Field` showed them as the only two of seven registered auto-number fields carrying createable=1/updateable=1. Layout code (`isAutoLayoutSectionExcluded`) additionally recognises the registry directly, so a mis-declared field is still hidden from editable layout sections. That safety net is why the drift stayed invisible; it does not make the `string` declaration correct. """ import json import unittest from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] PACK_ROOT = REPO_ROOT / "salesforce-crm-standard" AUTONUMBER_FORMATS = PACK_ROOT / "autonumber" / "formats.json" OBJECT_SPEC = PACK_ROOT / "objects" / "standard_objects_spec.json" AUTONUMBER_TYPE = "autonumber" def load_registered_autonumber_fields(): payload = json.loads(AUTONUMBER_FORMATS.read_text()) entries = payload if isinstance(payload, list) else payload.get("formats", []) return {(e["objectName"], e["fieldApiName"]) for e in entries} def load_declared_field_types(): payload = json.loads(OBJECT_SPEC.read_text()) declared = {} def walk(node): if isinstance(node, dict): object_api_name = node.get("apiName") or node.get("name") if object_api_name and isinstance(node.get("fields"), list): for field in node["fields"]: field_api_name = field.get("apiName") or field.get("name") if field_api_name: declared[(object_api_name, field_api_name)] = field.get("type") for value in node.values(): walk(value) elif isinstance(node, list): for value in node: walk(value) walk(payload) return declared class AutoNumberFieldDeclarationTests(unittest.TestCase): def test_registered_autonumber_fields_are_declared_autonumber(self): registered = load_registered_autonumber_fields() self.assertTrue(registered, "auto-number registry is empty; wrong path?") declared = load_declared_field_types() undeclared = sorted(k for k in registered if k not in declared) self.assertEqual( undeclared, [], "registered as auto-number but the field is not declared at all: " f"{undeclared}", ) mistyped = sorted( (obj, field, declared[(obj, field)]) for obj, field in registered if declared[(obj, field)] != AUTONUMBER_TYPE ) self.assertEqual( mistyped, [], "these fields are registered with the auto-number engine but declared " f'with another type, so the write path still treats them as writable: {mistyped}', ) if __name__ == "__main__": unittest.main()