@cratis/pi 7.127.0 → 7.128.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.
@@ -13,7 +13,7 @@ that read one contract, produced from the model and a Cratis environment:
13
13
  |---|---|---|
14
14
  | **AuthProxy** | The only public entry point; signs people in with the model's providers. | `Cratis:AuthProxy:Application` (see the AuthProxy reference of `cratis-arc-authentication-authorization-and-identity`). |
15
15
  | **Ante** | **One per application.** Signs invitation tokens, serves the lobby, records acceptance and legal terms, publishes to its outbox. | `Ante:Onboarding:*`. |
16
- | **Herald** | Sends the invitation and welcome emails from the application (the declined template waits for an Ante outcome). | `cratis-showrunner-herald`. |
16
+ | **Herald** | Sends the invitation and welcome emails from the application (including the declined sign-up email). | `cratis-showrunner-herald`. |
17
17
 
18
18
  Nobody writes the equivalent `Ante:*` or `Cratis:AuthProxy:*` keys by hand for a Screenplay
19
19
  application. The model supplies structure (providers, personas, invitation types, legal files);
@@ -29,7 +29,7 @@ persona and invitation-type checks. The **application** owns the persona list (t
29
29
  invited, link delivery, membership and provisioning. Ante sends no email: the application sends
30
30
  the invitation link through Herald using the `InvitationTokenIssued` token. Every accepted fact
31
31
  (`InvitationToJoinTenantAccepted`, `InvitationToCreateTenantAccepted`,
32
- `OrganizationRegistrationCompleted`, `LegalTermsAccepted`) means **published to Ante's outbox, not
32
+ `OrganizationRegistrationCompleted`, `OrganizationRegistrationDeclined`, `LegalTermsAccepted`) means **published to Ante's outbox, not
33
33
  provisioned**: make provisioning idempotent by event source id and event kind. Ante does not know
34
34
  what a persona may do; it validates grantable personas against the configured list only.
35
35
 
@@ -46,6 +46,12 @@ for the table before configuring anything.
46
46
  - Legal terms are files in a mounted folder (`terms.md`, `privacy.md`). The version is a content hash, so editing either file requires everyone onboarding afterwards to accept again. Archive each version for consent audit; the bodies live in your files.
47
47
  - **Secrets** (the signing private key, pinned attestation public keys) arrive only as mounted files or standard configuration, never on the command line; Ante logs no value.
48
48
 
49
+ ## Sign-up review and the default offering
50
+
51
+ - **Sign-up review** is opt-in (`Ante:Registration:Review`, off by default): Ante holds each sign-up until the host decides. Read [sign-up review](references/sign-up-review.md) before turning it on or handling `OrganizationRegistrationAwaitingReview`.
52
+ - **The default offering** starts each new tenant on the offer the product declared, through Box Office. Read [default offering](references/default-offering.md) before wiring `IDefaultOffering` or diagnosing a tenant without seats or modules.
53
+ - `InvitationRejected` is a host configuration problem, never a message to the invitee; only `OrganizationRegistrationDeclined` says a person was turned down.
54
+
49
55
  ## Development mode is for local runs only
50
56
 
51
57
  `Ante:Onboarding:Development:Enabled=true` generates a 2048-bit RSA signing key per data volume and
@@ -76,6 +82,7 @@ with its AuthProxy when the application has `authentication` and its own Ante wh
76
82
  - Treating `Accepted` as provisioned: provisioning is the application's, and must be idempotent.
77
83
  - Setting a signing key or provider secret as an environment variable in a manifest: use the mounted files.
78
84
  - Two Ante instances for one application, or one Ante shared by several Performances: one Ante per Performance, with its own event store (`ante-<name>` by default).
85
+ - Answering `InvitationRejected` with a message to the invitee: fix the invitation or host configuration instead.
79
86
  - Using development mode in a shared cluster: Ante refuses; do not work around the guard.
80
87
 
81
88
  ## Verify
@@ -90,5 +97,6 @@ with its AuthProxy when the application has `authentication` and its own Ante wh
90
97
  - The model's `onboarding` block and environment keys: `cratis-screenplay-authentication-and-onboarding`.
91
98
  - Environment commands and secrets providers: `cratis-environments-and-secrets`.
92
99
  - Sending the emails: `cratis-showrunner-herald`.
100
+ - Box Office offers, seats and entitlements beyond the default offering: Showrunner's Box Office documentation; this corpus covers only starting a tenant on the default offering.
93
101
  - Ante used by a host product, not a Screenplay application: Ante's own documentation; this corpus does not cover it.
94
102
  - Chronicle itself in a cluster: `cratis-chronicle-hosting`.
@@ -0,0 +1,61 @@
1
+ # Default offering
2
+
3
+ Requires Showrunner 1.13.0 or later (`Cratis.Showrunner.BoxOffice`) for `DefaultOffering`,
4
+ `IDefaultOffering` and an event store taken from the host. Older releases have neither.
5
+
6
+ A product that sells itself starts a new tenant on its default offering without waiting for the
7
+ operator. The product decides, the operator is told, and a later operator decision replaces it.
8
+
9
+ ## Declare it
10
+
11
+ ```csharp
12
+ builder.Services.AddBoxOfficeOffering(offering => offering
13
+ .Product(productId)
14
+ .Seats(SeatLicensing.PerUser)
15
+ .DefaultOffering("Starter"));
16
+ ```
17
+
18
+ The name is the offer in the operator's catalog. The declaration is reported once per change as
19
+ `DefaultOfferingDeclared`, so the operator knows which offer new tenants start on. A declaration
20
+ that cannot be sold throws `InvalidOffering` at startup, one sentence per problem.
21
+
22
+ ## Start a tenant
23
+
24
+ Call `IDefaultOffering.StartTenant(tenant, organization)` when the product has created the tenant.
25
+ It finds the named offer among the offers the operator published and does two things:
26
+
27
+ - records `TenantStartedOnDefaultOffering` in the tenant's own stream, so the tenant has the offer's
28
+ included seats and modules at once, with no trial;
29
+ - publishes `TenantStartedOnOffer` to the operator, with the offer's name, included seats and
30
+ modules.
31
+
32
+ A later operator decision such as `SeatCapacitySet` or `ModuleRevoked` supersedes what the tenant
33
+ started with: the newest decision wins.
34
+
35
+ ## Failures
36
+
37
+ | Failure | Meaning | Action |
38
+ |---|---|---|
39
+ | `DefaultOfferingNotDeclared` | The product declared no default offering. | Add `DefaultOffering(...)`. |
40
+ | `DefaultOfferingNotPublished` | The operator has not published an offer with that name, or withdrew it. The name compares ignoring case. | Publish the offer; retry. |
41
+ | `TenantNotStarted` | The tenant could not be started. | Read the reason; retry. |
42
+
43
+ The catalog arrives after the product starts, so a name is checked when a tenant starts, not at
44
+ startup. Nothing is published on a failure. Starting the same tenant again, also from another
45
+ instance, returns `TenantStart.AlreadyStarted` and publishes nothing; if the product stopped
46
+ between the two facts, starting again completes what is missing. A different default later does
47
+ not restart a tenant.
48
+
49
+ ## Event store
50
+
51
+ Herald, Box Office and the offering record in the host application's own event store in a host set
52
+ up with `AddCratis` or `AddCratisChronicle`; nothing needs naming. Set `HeraldOptions.EventStore`,
53
+ `BoxOfficeOptions.EventStore` or `OfferingOptions.EventStore` only to use another store. A host that
54
+ registers only the Chronicle client uses the name in `ChronicleClientOptions.EventStore`.
55
+
56
+ ## Verify
57
+
58
+ 1. After the operator publishes the offer, `StartTenant` for a new tenant publishes
59
+ `TenantStartedOnOffer`; a second call returns `TenantStart.AlreadyStarted`.
60
+ 2. Before the offer is published, `StartTenant` throws `DefaultOfferingNotPublished` and publishes
61
+ nothing.
@@ -0,0 +1,52 @@
1
+ # Sign-up review
2
+
3
+ Requires Ante 1.6.0 or later (`Ante:Registration:Review`, `RegistrationReview` in the onboarding
4
+ contract). Older releases complete every sign-up without a decision and publish neither event
5
+ below.
6
+
7
+ Review is off by default and changes nothing while off. Turn it on when a person must be approved
8
+ before an organization is created.
9
+
10
+ ## Flow
11
+
12
+ 1. A person finishes the sign-up. With review on, Ante accepts it but holds it: no
13
+ `OrganizationRegistrationCompleted` is published and the registration is not complete.
14
+ 2. Ante publishes `OrganizationRegistrationAwaitingReview` to its outbox, once per registration, on
15
+ the registration id. It carries the same details `OrganizationRegistrationCompleted` would carry:
16
+ the organization name asked for, the contact address (can be empty, never verified), the names,
17
+ the sign-in subject and provider, and the untrusted sign-up context.
18
+ 3. The host shows the sign-up to its reviewers. Ante has no administrator screen and takes no
19
+ decision itself.
20
+ 4. The host appends one of these to **its own store's outbox**, with the registration id as the
21
+ event source id:
22
+ - `OrganizationRegistrationApproved`: Ante completes the registration as it would have without
23
+ review and publishes `OrganizationRegistrationCompleted`.
24
+ - `OrganizationRegistrationDeclineRequested(Message)`: Ante publishes
25
+ `OrganizationRegistrationDeclined` with the contact address, the name the person gave and the
26
+ reviewer's message. `Message` is required; a blank one is refused and nothing is published.
27
+
28
+ ## Rules
29
+
30
+ - A registration is decided once. A decision for a registration that was completed, was already
31
+ declined or was never held is ignored, so redelivery is safe and a completed registration is
32
+ never declined afterwards.
33
+ - Deduplicate `OrganizationRegistrationAwaitingReview` by registration id, like every Ante outcome:
34
+ delivery is at least once.
35
+ - If an approved registration's organization name was claimed by someone else while it waited, it
36
+ stays held and Ante logs a warning. Decline it with a message instead.
37
+ - While a sign-up is held the lobby tells the person it is waiting for review; after a decline it
38
+ says the sign-up was not approved, stops polling and offers no second submission.
39
+ - Ante emails no one. The host sends the person the declined message from
40
+ `OrganizationRegistrationDeclined` (Herald, `signupDeclined` template with `decline.message`).
41
+ - `OrganizationRegistrationDeclined` is the only outcome that says a person was turned down.
42
+ `InvitationRejected` says an invitation did not match what the host allows; treat it as a
43
+ configuration problem for whoever issued the invitation.
44
+
45
+ ## Verify
46
+
47
+ 1. With review on, a sign-up produces `OrganizationRegistrationAwaitingReview` and no
48
+ `OrganizationRegistrationCompleted`.
49
+ 2. Appending `OrganizationRegistrationApproved` on the registration id produces
50
+ `OrganizationRegistrationCompleted`; appending it again produces nothing.
51
+ 3. A decline request with a blank message publishes nothing; with a message it publishes
52
+ `OrganizationRegistrationDeclined` once.
@@ -69,7 +69,7 @@ block. The diagnostics for each rule are in that reference. The rules that decid
69
69
  `signup open creates tenant` makes a signup create a tenant, `signup open joins tenant` asks to join an existing one.
70
70
  - Every persona in `as`, `by` and `grant` must be declared with `persona`; there are no free-text roles.
71
71
  - `emails` names only `invitation`, `welcome` and `signupDeclined`. The sender and mail server are not in the model.
72
- - `file` paths are repository-relative, like handler files. `offering` is an opaque name resolved where the application is provisioned.
72
+ - `file` paths are repository-relative, like handler files. `offering` is the name of an offer the operator publishes in Box Office; a rendered application starts each new tenant on it. `signupDeclined` is sent when the host declines a held sign-up (review is not modeled; see `cratis-onboarding-runtime`).
73
73
 
74
74
  ## Environment keys
75
75
 
@@ -66,7 +66,7 @@ Syntax and meaning of each line of the `onboarding` block. All lines are optiona
66
66
  | `invite tenant` | `invite tenant as <Persona>` | An invitation that creates a tenant; the invitee becomes the persona in it. One line, no body. |
67
67
  | `invite member` | body with `by <Persona>, ...` and `grant <Persona>, ...` | An invitation into an existing tenant. `by` lists who may send it, `grant` what the invitee is given. Both are required. |
68
68
  | `legal terms` | body of `file <path>` lines | Documents a newcomer must accept. Present means acceptance is required. |
69
- | `offering` | `offering <Id>` | The offering a new tenant starts on. Opaque; absent means no licensing. |
69
+ | `offering` | `offering <Id>` | The Box Office offer a new tenant starts on. Absent means no licensing. |
70
70
  | `emails` | body of `<email> file <path>` lines and `images <folder>` | Templates for `invitation`, `welcome` and `signupDeclined`, and the folder they take images from. |
71
71
 
72
72
  ## What the block deliberately lacks
@@ -12,6 +12,10 @@ as events in the application's own Chronicle event store. It is not a service.
12
12
 
13
13
  **Requires** `Cratis.Showrunner.Herald` 1.10.0 or later and an application that is a Chronicle
14
14
  client (`AddCratis` or `AddCratisChronicle`); check the package reference in the `.csproj`.
15
+ Herald records in the host application's own event store, without naming it again; set
16
+ `HeraldOptions.EventStore` only to use another store. Showrunner 1.13.0 or later takes the host's
17
+ store; an older release takes the name from the Chronicle client options, which an ASP.NET Core
18
+ host leaves empty, so set `EventStore` explicitly there.
15
19
 
16
20
  ## Add it
17
21
 
@@ -41,6 +45,7 @@ builder.AddHerald(herald =>
41
45
  validated at startup and the error names the option.
42
46
  - Defaults worth knowing: `DefaultLanguage` `en`, `Transport` `Smtp`, `Smtp.Security` `StartTls`,
43
47
  `Retry.MaxAttempts` 6, `PollingInterval` 5 seconds. Read [options](references/options.md) for the full table.
48
+ - A `signupDeclined` email is sent from `OrganizationRegistrationDeclined` with the reviewer's message as a value; see `cratis-onboarding-runtime`.
44
49
  - Chronicle finds Herald's events through type discovery of referenced `Cratis*` packages.
45
50
  - Run the worker in **one** application instance: delivery is at least once.
46
51
 
@@ -127,15 +127,24 @@ Requires cratis CLI 3.116.0 with Stage 4.211.0 (`cratis --version`); older relea
127
127
  - Only provider kinds AuthProxy supports render (`EntraId`, `GitHub`, `Google`, `Apple`,
128
128
  `OpenId`). Another kind is left out with `STAGE-AUTH-001`; a persona that is not a
129
129
  requirement on authentication, roles or claims is never matched (`STAGE-AUTH-002`).
130
- - `offering` renders nothing (`STAGE-ONBOARDING-001`): tenants are provisioned without
131
- licensing. `STAGE-ONBOARDING-002` to `-006` cover a tenant invitation with no command,
130
+ - `offering <Name>` renders against Box Office: the default offering is declared, and a
131
+ retrying reactor on tenant provisioning starts each new tenant on it (`StartTenant`) as soon as
132
+ the operator publishes the offer. Provisioning and the welcome email do not wait for it.
133
+ `STAGE-ONBOARDING-008` is information: the operator must publish an offer with that name, and
134
+ Box Office seat and compute policies are not rendered. Requires Stage 4.212.0
135
+ for the offering and the declined email; older renderers render neither.
136
+ `STAGE-ONBOARDING-002` to `-006` cover a tenant invitation with no command,
132
137
  a sign-up without a first-member persona, a legal document count other than two, a
133
- missing email template and an invitation without inviters.
138
+ missing email template and an invitation without inviters. `-001` and `-007` are retired
139
+ and never reused.
134
140
  - An invitation Ante rejects (a persona or invitation type the model does not allow) is a
135
141
  mistake in the invitation, not a decision about the person: the application records
136
142
  `OnboardingInvitationRejected` and logs a warning for an administrator, and emails no
137
- one. The `signupDeclined` template renders but is not sent until Ante publishes a
138
- declined sign-up (`STAGE-ONBOARDING-007`).
143
+ one.
144
+ - The `signupDeclined` template is sent on `OrganizationRegistrationDeclined`, with the
145
+ reviewer's message as `decline.message`, once per registration. Ante publishes that only
146
+ when sign-up review is on; the model has no review syntax, so a rendered application leaves
147
+ review off and the host adds approve and decline commands by hand (`cratis-onboarding-runtime`).
139
148
  - An application with onboarding pins a newer Chronicle client and kernel image than
140
149
  other applications; read them from the rendered files.
141
150
  - Realization needs the model folder: email images are read from the model root.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/pi",
3
- "version": "7.127.0",
3
+ "version": "7.128.0",
4
4
  "description": "Configuration-aware Cratis AI integration for Pi",
5
5
  "type": "module",
6
6
  "files": [