@odla-ai/chapter 0.44.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -859,6 +859,47 @@ and relations by composing its own config before passing it to Chapter.
859
859
  Formation is off unless configured. Chapter intentionally does not ship a
860
860
  public form design: the site renders the fields in its own voice and brand.
861
861
 
862
+ ### Shared-Stripe commercial shadow
863
+
864
+ A hub may opt into a read-only network commercial projection when multiple
865
+ chapters intentionally bill through one Stripe account. Every accepted source
866
+ is an exact partition, including Stripe test/live mode:
867
+
868
+ ```ts
869
+ networkCommercialReadModel: {
870
+ mode: "shadow",
871
+ sources: [{
872
+ stripeMode: "test",
873
+ appId: "example-chapter",
874
+ chapterId: "example-chapter",
875
+ environment: "dev",
876
+ dataEnvironment: "dev",
877
+ runtime: "cory",
878
+ }],
879
+ },
880
+ ```
881
+
882
+ The dedicated `/api/network-commercial/stripe-webhook` verifies Stripe's
883
+ signature with `network_commercial_stripe_webhook_secret` before writing an
884
+ append-only, PII-free event fact. The projector is rebuildable and deterministic:
885
+ late metadata-less events may inherit a partition only through an unambiguous
886
+ provider customer/subscription/invoice/charge reference. Wrong, missing,
887
+ ambiguous, unsupported, and colliding events remain explained exceptions.
888
+
889
+ `GET /api/admin/network-commercial-read-model` is super-admin-only and exposes
890
+ current customer, subscription, invoice, refund, and currency-total facts for a
891
+ BNF operator surface. `POST` with `{ command: "rebuild", mutationId }` rebuilds
892
+ from the local event log without calling or mutating Stripe. `POST` with
893
+ `{ command: "reconcile-stripe" }` performs bounded, GET-only current-object
894
+ reads through the hub's vaulted `stripe_secret_key` and reports missing,
895
+ unexpected, mismatched, truncated, and totals exceptions without changing the
896
+ event log or projection. Objects outside the configured exact partitions are
897
+ counted as ignored rather than adopted. This shadow never
898
+ authorizes charges, refunds, subscription changes, or Chapter lifecycle writes;
899
+ removing it changes no customer-facing behavior. The BNF frontend may be down
900
+ while the webhook continues to ingest. Registering a Stripe endpoint and
901
+ enabling production remain separate reviewed operations.
902
+
862
903
  For a hub with network targets, the standard admin catalog is Dashboard,
863
904
  Network, People, Portfolio, and Settings. Dashboard Overview renders aggregate network
864
905
  health; People contains CRM types whose `workspace` is absent or `"people"`;
@@ -147,6 +147,26 @@ interface ResolvedNetworkPersonRegistry {
147
147
  chapterIds: readonly string[];
148
148
  }
149
149
 
150
+ /** One exact Stripe event partition accepted by the network commercial shadow. */
151
+ interface NetworkCommercialSource {
152
+ appId: string;
153
+ chapterId: string;
154
+ environment: string;
155
+ dataEnvironment: string;
156
+ runtime: string;
157
+ stripeMode: "test" | "live";
158
+ }
159
+ /** Opt-in, read-only projection of a shared Stripe account. */
160
+ interface ChapterNetworkCommercialReadModel {
161
+ mode: "shadow";
162
+ sources: readonly NetworkCommercialSource[];
163
+ }
164
+ /** Validated settings carried by a resolved hub. */
165
+ interface ResolvedNetworkCommercialReadModel {
166
+ mode: "shadow";
167
+ sources: readonly NetworkCommercialSource[];
168
+ }
169
+
150
170
  /** Scalar kinds accepted by the Chapter schema adapter. */
151
171
  type AttrType = "string" | "number" | "boolean" | "json";
152
172
  /** One odla-db attribute: its type and index/uniqueness/optionality flags. */
@@ -554,6 +574,8 @@ interface ChapterConfig {
554
574
  /** Network-scoped canonical Person registry. Shadow mode is additive only:
555
575
  * Chapter workflows and access continue to read their existing authority. */
556
576
  networkPersonRegistry?: ChapterNetworkPersonRegistry;
577
+ /** Read-only, rebuildable commercial projection from a shared Stripe account. */
578
+ networkCommercialReadModel?: ChapterNetworkCommercialReadModel;
557
579
  /** Enable a public, host-rendered formation application workflow. */
558
580
  formation?: LeaderFormationConfig;
559
581
  thesis?: unknown;
@@ -656,6 +678,8 @@ interface Chapter {
656
678
  builderLibrary: ResolvedBuilderLibrary | null;
657
679
  /** Null unless this hub explicitly enables the shadow Person registry. */
658
680
  networkPersonRegistry: ResolvedNetworkPersonRegistry | null;
681
+ /** Null unless this hub explicitly enables the commercial shadow. */
682
+ networkCommercialReadModel: ResolvedNetworkCommercialReadModel | null;
659
683
  /** Resolved public formation intake contract (disabled when omitted). */
660
684
  formation: ResolvedLeaderFormation;
661
685
  /** Resolved CRM engine (from `defineCrm`). */