Chronicle code analysis
As of .NET v22.23.0, Arc shipped ten Chronicle analyzers (ARCCHR0001–ARCCHR0010); this mapping covers that set.
Five have bounded TypeScript ESLint analogs in @cratis/eslint-plugin-arc-core.
Configure the plugin as described in Code analysis.
Both presets enable arcchr0003, arcchr0007, and arcchr0009.
arcchr0006 and arcchr0010 need type information and are enabled by recommended-type-checked.
ESLint reports enabled rules as errors, including analogs of .NET warnings.
ARCCHR mapping
Section titled “ARCCHR mapping”| .NET diagnostic | .NET default | TypeScript status |
|---|---|---|
| ARCCHR0001, aggregate handler signature | Error | N/A |
| ARCCHR0002, ambiguous command identity | Warning | N/A / runtime |
| ARCCHR0003, reactor reaches default log | Warning | ESLint analog |
ARCCHR0004, redundant [EventType] id | Warning | N/A |
| ARCCHR0005, Chronicle used but not configured | Warning | Partly caught at runtime |
| ARCCHR0006, reactor returns a command without a replay decision | Warning | Type-checked ESLint analog |
| ARCCHR0007, command injects event log | Warning | ESLint analog |
ARCCHR0008, data annotations [Key] | Warning | N/A |
| ARCCHR0009, secret-looking command property | Warning | ESLint analog for names not masked at runtime |
| ARCCHR0010, raw GUID response | Warning | Type-checked ESLint analog |
- ARCCHR0001:
this.on(EventClass, handler)registers a typed callback; duplicate handlers throw. NoOnmethod-signature convention exists. - ARCCHR0002:
getEventSourceId(),getKey(), or one@key()determines the key. A second@key()throws when the class is defined. - ARCCHR0003: The rule finds direct
eventLog.appendorappendManycalls through athisfield initialized fromthis.client.getEventStoreorthis.runtime.getStore. It cannot prove the field’s store belongs to the reactor; it ignores fields initialized from another client. Return events instead. - ARCCHR0004: An explicit TypeScript SDK ID equal to the class name stabilizes persisted type identity across minification or renaming. Removing it changes guarantees.
- ARCCHR0005:
commandReadModel(Type)without an owner failsbuild(). A returned event withoutwithChroniclebecomes an ordinary response and is not caught. A per-file ESLint rule cannot prove registration in a separate host module. - ARCCHR0006: TypeScript reactors return Arc commands rather than calling .NET’s
ICommandPipeline.Execute. The type-checked rule follows same-class helper calls back to live handlers and warns when none has a replay decision. Class- or handler-level@onceOnly()and an@replay()handler for the same event silence it. Dispatch matches the camel-cased event class name, not the parameter annotation. See the rule’s bounds. - ARCCHR0007: The rule finds direct
eventLog.appendorappendManycalls from a command’shandle()orprovide()through an artifact store or a@inject(ChronicleReadModels | ChronicleRuntime)parameter, including local and inlinegetStore()calls. Indirect appends remain a review concern. - ARCCHR0008: TypeScript has only Arc’s
@key(); there is no competing data-annotations decorator. - ARCCHR0009: Arc withholds names containing
password,secret,token,credential, orapiKey, and fields marked@notAudited()or@pii(). The rule checks the remaining .NET secret words, including Passphrase, PrivateKey, and AuthorizationHeader, without falsely claiming masked names are written to causation. - ARCCHR0010: A keyless command returning
tuple(Guid.create(), new DecoratedEvent())returns an ordinary response instead of selecting the event source. The type-checked rule also recognizes Guid variables andGuid.parse(...); it does not infer plain strings, indirect event factories, inherited event-type decorators, or other tuple shapes.
As of .NET v22.23.0, there was no ARCCHR analyzer for nullable event properties or past-tense event names; this mapping does not add either rule.
What to check in review
Section titled “What to check in review”- Appends through helper methods or stores not held directly by a command or reactor can bypass the return-value pipeline.
- Commands executed manually inside a reactor (for example through an Arc server) are not detected.
They still need a replay decision;
@onceOnly()skips replay but does not prevent failed-partition re-delivery. See Returning commands from a reactor. - An app that returns events must install
withChronicle; check the host, not just the artifact file. - A tuple carrying an ordinary string instead of
eventSourceIdResponse(id)does not select an event source; see Resolving the event source ID.