Skip to content

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.

.NET diagnostic.NET defaultTypeScript status
ARCCHR0001, aggregate handler signatureErrorN/A
ARCCHR0002, ambiguous command identityWarningN/A / runtime
ARCCHR0003, reactor reaches default logWarningESLint analog
ARCCHR0004, redundant [EventType] idWarningN/A
ARCCHR0005, Chronicle used but not configuredWarningPartly caught at runtime
ARCCHR0006, reactor returns a command without a replay decisionWarningType-checked ESLint analog
ARCCHR0007, command injects event logWarningESLint analog
ARCCHR0008, data annotations [Key]WarningN/A
ARCCHR0009, secret-looking command propertyWarningESLint analog for names not masked at runtime
ARCCHR0010, raw GUID responseWarningType-checked ESLint analog
  • ARCCHR0001: this.on(EventClass, handler) registers a typed callback; duplicate handlers throw. No On method-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.append or appendMany calls through a this field initialized from this.client.getEventStore or this.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 fails build(). A returned event without withChronicle becomes 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.append or appendMany calls from a command’s handle() or provide() through an artifact store or a @inject(ChronicleReadModels | ChronicleRuntime) parameter, including local and inline getStore() 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, or apiKey, 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 and Guid.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.

  • 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.