|
9 | 9 | // The journey is the whole sign-up a walled deployment sees: a stranger |
10 | 10 | // self-registers (the verification mail is sent), creates their organization |
11 | 11 | // (their first membership), and invites a second stranger (the invitation |
12 | | -// mail is sent), who self-registers and accepts it (their first membership). |
| 12 | +// mail is sent), who signs up and accepts it (their first membership). |
13 | 13 | // Three framework writers act on tenant-column objects along the way, and on |
14 | 14 | // a wall none of them may fall back to an organization-less row: |
15 | 15 | // |
16 | | -// - the self-registration grant (`sys_user_permission_set`) settles on each |
17 | | -// registrant's FIRST MEMBERSHIP, owned by that membership's organization |
18 | | -// (ADR-0131 D3) — never at sign-up, when there is no organization yet; |
| 16 | +// - the self-registration grant (`sys_user_permission_set`) settles on the |
| 17 | +// self-registrant's FIRST MEMBERSHIP, owned by that membership's |
| 18 | +// organization (ADR-0131 D3) — never at sign-up, when there is no |
| 19 | +// organization yet; the invitee is admitted by the invitation, not by the |
| 20 | +// open posture, and is owed no declared set; |
19 | 21 | // - the activity writer (`sys_activity`) stamps the organization of the |
20 | 22 | // record it is about, and writes NO row about a record that has none |
21 | 23 | // (ADR-0131 D9; ruling of record 6257510973 item 3, Q3 A); |
@@ -197,18 +199,25 @@ for (const posture of ['group', 'isolated'] as const) { |
197 | 199 | expect(foreign, 'rows owned by an organization other than the journey\'s').toEqual([]); |
198 | 200 | }); |
199 | 201 |
|
200 | | - it('the grant writer: each registrant holds exactly one declared grant, owned by their first membership', async () => { |
201 | | - for (const userId of [registrantId, inviteeId]) { |
202 | | - const grants = await ql.find('sys_user_permission_set', { where: { user_id: userId }, ...SYS }); |
203 | | - expect(grants.map((g: Row) => [g.permission_set, g.organization_id]), `${userId}: grants`).toEqual([[SET, orgId]]); |
204 | | - } |
| 202 | + it('the grant writer: the self-registrant holds exactly one declared grant, owned by their first membership', async () => { |
| 203 | + const grants = await ql.find('sys_user_permission_set', { where: { user_id: registrantId }, ...SYS }); |
| 204 | + expect(grants.filter((g: Row) => g.permission_set === SET).map((g: Row) => g.organization_id), 'the declared grant').toEqual([orgId]); |
| 205 | + // The creator's `organization_admin` (the auto org-admin grant) rides |
| 206 | + // the same membership; every grant names the organization. |
| 207 | + expect(grants.filter((g: Row) => g.organization_id !== orgId), 'grants outside the organization').toEqual([]); |
| 208 | + // The invitee was admitted by the invitation, not by the open posture, so |
| 209 | + // is owed no declared set (`decideAudienceAdmission`); whatever it holds |
| 210 | + // names the organization too. |
| 211 | + const inviteeGrants = await ql.find('sys_user_permission_set', { where: { user_id: inviteeId }, ...SYS }); |
| 212 | + expect(inviteeGrants.filter((g: Row) => g.permission_set === SET), 'the invitee holds no declared grant').toEqual([]); |
| 213 | + expect(inviteeGrants.filter((g: Row) => g.organization_id !== orgId), 'invitee grants outside the organization').toEqual([]); |
205 | 214 | }); |
206 | 215 |
|
207 | 216 | it('the activity writer: activity about each grant and about the invitation mail names the organization', async () => { |
208 | 217 | const written = await journeyRows(); |
209 | 218 | const activity = written.filter((r) => r.table === 'sys_activity' || r.table.startsWith('sys_activity__')); |
210 | | - const grants = await ql.find('sys_user_permission_set', { where: { user_id: { $in: [registrantId, inviteeId] } }, ...SYS }); |
211 | | - expect(grants.length).toBe(2); |
| 219 | + const grants = await ql.find('sys_user_permission_set', { where: { user_id: registrantId }, ...SYS }); |
| 220 | + expect(grants.map((g: Row) => g.permission_set), 'the registrant\'s grants').toContain(SET); |
212 | 221 | for (const grant of grants) { |
213 | 222 | const about = activity.filter((a) => a.object_name === 'sys_user_permission_set' && a.record_id === grant.id); |
214 | 223 | expect(about.length, `activity about the grant ${String(grant.id)}`).toBeGreaterThan(0); |
|
0 commit comments