@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.
- package/package/corpus/skills/cratis-onboarding-runtime/SKILL.md +10 -2
- package/package/corpus/skills/cratis-onboarding-runtime/references/default-offering.md +61 -0
- package/package/corpus/skills/cratis-onboarding-runtime/references/sign-up-review.md +52 -0
- package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md +1 -1
- package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md +1 -1
- package/package/corpus/skills/cratis-showrunner-herald/SKILL.md +5 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +14 -5
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md
CHANGED
|
@@ -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
|
|
131
|
-
|
|
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.
|
|
138
|
-
|
|
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.
|