Skip to content

Add regulatory_identity (CRD number) field to approval receipt schema for FINRA Rule 3110(d) compliance #51

Description

@VladUZH

Problem

The current SidClaw approval receipt schema captures reviewer_id (an internal identifier) when a human approves a held tool call. For broker-dealer compliance use cases (notably FINRA Rule 3110(d) Transaction Review), the receipt must also capture the registered principal's regulatory identity — specifically the FINRA CRD number of the approving supervisor.

A FINRA examiner reviewing a broker-dealer's supervisory records expects to see, on each transaction review record:

  • Who approved (name + CRD number)
  • What license type they hold (Series 24 General Securities Principal, Series 9/10, etc.)
  • What regulatory jurisdiction the approval covers (FINRA, SEC-only, state)

Without this, the receipt is technically signed and verifiable, but not regulator-readable for FINRA examination purposes.

Proposed solution

Add an optional regulatory_identity block inside the canonical signed payload (NOT envelope metadata — must survive verification per the existing reviewer-binding pattern):

canonical_payload: {
  policy_hash,
  policy_eval_ts,
  reviewer_id,
  reviewer_decision_ts,
  decision_outcome,
  regulatory_identity: {           // NEW, optional
    crd_number: "1234567",          // FINRA Central Registration Depository number
    license_type: "Series 24",      // Or "Series 9/10", "Series 4", etc.
    jurisdiction: "FINRA",          // FINRA | SEC | state code | "none"
    registered_firm_crd: "98765"    // Optional: firm's CRD if relevant
  },
  ...tool_call_fields
}

Configuration surface

Static config (per-reviewer): When a reviewer is registered in the dashboard, allow optional regulatory_identity fields. Auto-populated on every approval that reviewer makes.

Per-approval override: When approving via dashboard or API, allow the reviewer to override or add regulatory_identity (e.g., reviewer holds multiple licenses and is approving in a specific capacity).

Backward compatibility

  • Field is OPTIONAL. Existing receipts without regulatory_identity continue to verify normally.
  • Verifier MUST treat missing field as valid (no breaking change).
  • Schema version bump (dcp-jcs-v1dcp-jcs-v1.1) so verifiers can opt into stricter mode that REQUIRES the field for trade-execution tool classes.

Validation

  • crd_number: must match /^\d{1,8}$/ (FINRA CRD numbers are 1-8 digit integers)
  • license_type: enum from documented list (Series 24, Series 9, Series 10, Series 4, Series 27, Series 28, custom string allowed with warning)
  • jurisdiction: enum {FINRA, SEC, state code (2-letter), "none"}
  • Dashboard sanity check: if crd_number is set, surface a "verify on FINRA BrokerCheck" link to the configurer (https://brokercheck.finra.org/individual/summary/<crd>)

Tests

  • Round-trip: build receipt with regulatory_identity, sign, verify → byte-identical
  • Round-trip: build receipt WITHOUT regulatory_identity, sign, verify → byte-identical (backward compat)
  • Schema validation rejects malformed CRD (e.g., "1234567X" or 9-digit)
  • Cross-language interop: TypeScript SDK and Python SDK produce identical canonical bytes for the same regulatory_identity input

Documentation

  • Update docs.sidclaw.com with new field documentation
  • Add a "FINRA Compliance" section to README that links to FINRA Rule 3110(d) text, BrokerCheck CRD lookup, and example approval flow with regulatory identity attached

Acceptance criteria

  1. CCO can demo SidClaw approval flow and the receipt JSON shows their CRD number inside the canonical signed bytes
  2. Independent verifier (TypeScript or Python) confirms byte-identity across SDKs
  3. Existing receipts without the field continue to verify
  4. dcp-jcs-v1.1 profile pinned and documented
  5. Documentation updated; README "FINRA Compliance" section linked from main page

Estimated effort

~1 week solo development:

  • Day 1: Schema design finalized, test vectors written
  • Day 2-3: TypeScript SDK implementation + tests
  • Day 3-4: Python SDK implementation + tests
  • Day 4-5: Dashboard config surface (reviewer profile + approval override)
  • Day 5: Docs + README + example
  • Day 6-7: Cross-language interop test, schema version bump, ship

Out of scope (separate issues)

  • WSP Addendum template (separate workstream)
  • SEC Rule 17a-4 retention webhook (Smarsh/Global Relay export)
  • FINRA Rule 4530 event reporting
  • SOC 2 Type II compliance

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions