@oxy.so/contracts 4.16.0 → 4.17.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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/accountEmail.js +12 -34
- package/dist/cjs/accountGraph.js +22 -320
- package/dist/cjs/agentKeys.js +11 -13
- package/dist/cjs/client/accountEmail.js +48 -0
- package/dist/cjs/client/accountGraph.js +323 -0
- package/dist/cjs/client/agentKeys.js +77 -0
- package/dist/cjs/client/check.js +466 -0
- package/dist/cjs/client/deviceBoot.js +22 -0
- package/dist/cjs/client/deviceDirectory.js +51 -0
- package/dist/cjs/client/deviceSession.js +63 -0
- package/dist/cjs/client/externalIdentity.js +19 -0
- package/dist/cjs/client/identity.js +45 -0
- package/dist/cjs/client/identityLink.js +55 -0
- package/dist/cjs/client/identityProof.js +109 -0
- package/dist/cjs/client/index.js +190 -0
- package/dist/cjs/client/organizations.js +114 -0
- package/dist/cjs/client/products.js +153 -0
- package/dist/cjs/client/recommendations.js +33 -0
- package/dist/cjs/client/reputation.js +41 -0
- package/dist/cjs/client/safety.js +15 -0
- package/dist/cjs/client/sessionStatus.js +23 -0
- package/dist/cjs/client/signIn.js +157 -0
- package/dist/cjs/client/userResponse.js +15 -0
- package/dist/cjs/client/username.js +173 -0
- package/dist/cjs/deviceSession.js +3 -16
- package/dist/cjs/identityLink.js +13 -34
- package/dist/cjs/identityProof.js +18 -106
- package/dist/cjs/organizations.js +21 -41
- package/dist/cjs/reputation.js +3 -34
- package/dist/cjs/signIn.js +33 -111
- package/dist/cjs/username.js +23 -158
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/accountEmail.js +4 -32
- package/dist/esm/accountGraph.js +4 -309
- package/dist/esm/agentKeys.js +4 -10
- package/dist/esm/client/accountEmail.js +45 -0
- package/dist/esm/client/accountGraph.js +314 -0
- package/dist/esm/client/agentKeys.js +74 -0
- package/dist/esm/client/check.js +428 -0
- package/dist/esm/client/deviceBoot.js +19 -0
- package/dist/esm/client/deviceDirectory.js +48 -0
- package/dist/esm/client/deviceSession.js +60 -0
- package/dist/esm/client/externalIdentity.js +16 -0
- package/dist/esm/client/identity.js +42 -0
- package/dist/esm/client/identityLink.js +50 -0
- package/dist/esm/client/identityProof.js +104 -0
- package/dist/esm/client/index.js +37 -0
- package/dist/esm/client/organizations.js +111 -0
- package/dist/esm/client/products.js +150 -0
- package/dist/esm/client/recommendations.js +30 -0
- package/dist/esm/client/reputation.js +37 -0
- package/dist/esm/client/safety.js +12 -0
- package/dist/esm/client/sessionStatus.js +20 -0
- package/dist/esm/client/signIn.js +151 -0
- package/dist/esm/client/userResponse.js +12 -0
- package/dist/esm/client/username.js +167 -0
- package/dist/esm/deviceSession.js +1 -15
- package/dist/esm/identityLink.js +4 -27
- package/dist/esm/identityProof.js +4 -99
- package/dist/esm/organizations.js +4 -31
- package/dist/esm/reputation.js +1 -32
- package/dist/esm/signIn.js +4 -96
- package/dist/esm/username.js +4 -148
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/accountEmail.d.ts +2 -34
- package/dist/types/accountGraph.d.ts +12 -208
- package/dist/types/agency.d.ts +24 -24
- package/dist/types/agentKeys.d.ts +8 -6
- package/dist/types/client/accountEmail.d.ts +44 -0
- package/dist/types/client/accountGraph.d.ts +203 -0
- package/dist/types/client/agentKeys.d.ts +113 -0
- package/dist/types/client/check.d.ts +184 -0
- package/dist/types/client/deviceBoot.d.ts +6 -0
- package/dist/types/client/deviceDirectory.d.ts +134 -0
- package/dist/types/client/deviceSession.d.ts +91 -0
- package/dist/types/client/externalIdentity.d.ts +14 -0
- package/dist/types/client/identity.d.ts +8 -0
- package/dist/types/client/identityLink.d.ts +21 -0
- package/dist/types/client/identityProof.d.ts +73 -0
- package/dist/types/client/index.d.ts +37 -0
- package/dist/types/client/organizations.d.ts +167 -0
- package/dist/types/client/products.d.ts +145 -0
- package/dist/types/client/recommendations.d.ts +27 -0
- package/dist/types/client/reputation.d.ts +28 -0
- package/dist/types/client/safety.d.ts +13 -0
- package/dist/types/client/sessionStatus.d.ts +19 -0
- package/dist/types/client/signIn.d.ts +107 -0
- package/dist/types/client/userResponse.d.ts +7 -0
- package/dist/types/client/username.d.ts +126 -0
- package/dist/types/deviceDirectory.d.ts +28 -28
- package/dist/types/deviceSession.d.ts +1 -12
- package/dist/types/externalIdentity.d.ts +11 -11
- package/dist/types/identityLink.d.ts +3 -11
- package/dist/types/identityProof.d.ts +2 -65
- package/dist/types/inference/decisions.d.ts +10 -10
- package/dist/types/inference/embeddings.d.ts +16 -16
- package/dist/types/inference/errors.d.ts +8 -8
- package/dist/types/inference/inbox.d.ts +8 -8
- package/dist/types/inference/privateAutoExecution.d.ts +6 -6
- package/dist/types/inference/realtime.d.ts +30 -30
- package/dist/types/inference/request.d.ts +28 -28
- package/dist/types/inference/streamEvents.d.ts +16 -16
- package/dist/types/inference/usage.d.ts +4 -4
- package/dist/types/oauth.d.ts +2 -2
- package/dist/types/organizations.d.ts +8 -10
- package/dist/types/products/billing.d.ts +3 -0
- package/dist/types/reputation.d.ts +1 -11
- package/dist/types/sessionStatus.d.ts +2 -2
- package/dist/types/signIn.d.ts +6 -89
- package/dist/types/userResponse.d.ts +20 -20
- package/dist/types/username.d.ts +1 -96
- package/package.json +20 -1
package/dist/cjs/accountEmail.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.emailVerificationConfirmResponseSchema = exports.emailVerificationConfirmRequestSchema = exports.emailVerificationStartResponseSchema = exports.emailVerificationStartRequestSchema = exports.emailTicketSchema = exports.emailAddressSchema = exports.EMAIL_VERIFICATION_ERROR_CODES = exports.EMAIL_TICKET_TTL_MS = exports.EMAIL_CODE_MAX_ATTEMPTS = exports.EMAIL_CODE_TTL_MS = exports.EMAIL_CODE_LENGTH = exports.EMAIL_VERIFICATION_PURPOSES = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Email codes and tickets (ADR 0030).
|
|
6
6
|
*
|
|
@@ -16,22 +16,16 @@ exports.EMAIL_VERIFICATION_ERROR_CODES = exports.emailVerificationConfirmRespons
|
|
|
16
16
|
* (`reauth`) use the same code, through their own routes (`signIn.ts`).
|
|
17
17
|
*/
|
|
18
18
|
const zod_1 = require("zod");
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
exports
|
|
27
|
-
|
|
28
|
-
exports.
|
|
29
|
-
/** How long a code can be confirmed. */
|
|
30
|
-
exports.EMAIL_CODE_TTL_MS = 10 * 60 * 1000;
|
|
31
|
-
/** Wrong codes before a verification is spent and a new code is needed. */
|
|
32
|
-
exports.EMAIL_CODE_MAX_ATTEMPTS = 5;
|
|
33
|
-
/** How long a confirmed code's ticket can be spent. */
|
|
34
|
-
exports.EMAIL_TICKET_TTL_MS = 15 * 60 * 1000;
|
|
19
|
+
// The Zod-free half of this contract lives in `./client/` (`@oxy.so/contracts/client`);
|
|
20
|
+
// it is re-exported here so the root entry is unchanged.
|
|
21
|
+
const accountEmail_1 = require("./client/accountEmail");
|
|
22
|
+
var accountEmail_2 = require("./client/accountEmail");
|
|
23
|
+
Object.defineProperty(exports, "EMAIL_VERIFICATION_PURPOSES", { enumerable: true, get: function () { return accountEmail_2.EMAIL_VERIFICATION_PURPOSES; } });
|
|
24
|
+
Object.defineProperty(exports, "EMAIL_CODE_LENGTH", { enumerable: true, get: function () { return accountEmail_2.EMAIL_CODE_LENGTH; } });
|
|
25
|
+
Object.defineProperty(exports, "EMAIL_CODE_TTL_MS", { enumerable: true, get: function () { return accountEmail_2.EMAIL_CODE_TTL_MS; } });
|
|
26
|
+
Object.defineProperty(exports, "EMAIL_CODE_MAX_ATTEMPTS", { enumerable: true, get: function () { return accountEmail_2.EMAIL_CODE_MAX_ATTEMPTS; } });
|
|
27
|
+
Object.defineProperty(exports, "EMAIL_TICKET_TTL_MS", { enumerable: true, get: function () { return accountEmail_2.EMAIL_TICKET_TTL_MS; } });
|
|
28
|
+
Object.defineProperty(exports, "EMAIL_VERIFICATION_ERROR_CODES", { enumerable: true, get: function () { return accountEmail_2.EMAIL_VERIFICATION_ERROR_CODES; } });
|
|
35
29
|
/** An email address as the API stores it: trimmed and lowercase. */
|
|
36
30
|
exports.emailAddressSchema = zod_1.z.string().trim().toLowerCase().min(3).max(254).email();
|
|
37
31
|
/** An opaque one-use ticket (32 random bytes, base64url). */
|
|
@@ -54,26 +48,10 @@ exports.emailVerificationConfirmRequestSchema = zod_1.z
|
|
|
54
48
|
code: zod_1.z
|
|
55
49
|
.string()
|
|
56
50
|
.trim()
|
|
57
|
-
.regex(new RegExp(`^\\d{${
|
|
51
|
+
.regex(new RegExp(`^\\d{${accountEmail_1.EMAIL_CODE_LENGTH}}$`), `code must be ${accountEmail_1.EMAIL_CODE_LENGTH} digits`),
|
|
58
52
|
})
|
|
59
53
|
.strict();
|
|
60
54
|
exports.emailVerificationConfirmResponseSchema = zod_1.z.object({
|
|
61
55
|
ticket: exports.emailTicketSchema,
|
|
62
56
|
expiresAt: zod_1.z.number().int().positive(),
|
|
63
57
|
});
|
|
64
|
-
/**
|
|
65
|
-
* Stable error codes (`error.code` in the API error body). Clients map these
|
|
66
|
-
* through their localization, never the English message.
|
|
67
|
-
*/
|
|
68
|
-
exports.EMAIL_VERIFICATION_ERROR_CODES = {
|
|
69
|
-
/** The code is wrong, or its verification expired or was spent. */
|
|
70
|
-
codeInvalid: 'EMAIL_CODE_INVALID',
|
|
71
|
-
/** Too many wrong codes: request a new one. */
|
|
72
|
-
tooManyAttempts: 'EMAIL_CODE_TOO_MANY_ATTEMPTS',
|
|
73
|
-
/** The ticket is unknown, expired, spent, or for another email or purpose. */
|
|
74
|
-
ticketInvalid: 'EMAIL_TICKET_INVALID',
|
|
75
|
-
/** A sign-up without a confirmed email. */
|
|
76
|
-
ticketRequired: 'EMAIL_TICKET_REQUIRED',
|
|
77
|
-
/** This server cannot send mail. */
|
|
78
|
-
unavailable: 'EMAIL_UNAVAILABLE',
|
|
79
|
-
};
|
package/dist/cjs/accountGraph.js
CHANGED
|
@@ -8,250 +8,30 @@
|
|
|
8
8
|
* {@link ACCOUNT_CATEGORY_IDS} for the four rules that govern it.
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.createAccountRequestSchema = exports.accountNameSchema = exports.
|
|
12
|
-
exports.isDelegatedActAsEligibleKind = isDelegatedActAsEligibleKind;
|
|
13
|
-
exports.isOperatorSwitchTargetKind = isOperatorSwitchTargetKind;
|
|
14
|
-
exports.isAccountKind = isAccountKind;
|
|
15
|
-
exports.isSelectableAccountCategoryId = isSelectableAccountCategoryId;
|
|
16
|
-
exports.newlyAddedRetiredCategories = newlyAddedRetiredCategories;
|
|
17
|
-
exports.kindAcceptsAccountCategories = kindAcceptsAccountCategories;
|
|
11
|
+
exports.createAccountRequestSchema = exports.accountNameSchema = exports.accountCategoriesSchema = exports.accountCategoryIdSchema = exports.childAccountKindSchema = exports.accountKindSchema = exports.kindAcceptsAccountCategories = exports.ACCOUNT_CATEGORY_KINDS = exports.MAX_ACCOUNT_CATEGORIES = exports.newlyAddedRetiredCategories = exports.SELECTABLE_ACCOUNT_CATEGORY_IDS = exports.isSelectableAccountCategoryId = exports.RETIRED_ACCOUNT_CATEGORY_IDS = exports.ACCOUNT_CATEGORY_IDS = exports.isAccountKind = exports.isOperatorSwitchTargetKind = exports.isDelegatedActAsEligibleKind = exports.CHILD_ACCOUNT_KINDS = exports.ACCOUNT_KINDS = void 0;
|
|
18
12
|
const zod_1 = require("zod");
|
|
19
13
|
const avatarCharacter_1 = require("./avatarCharacter");
|
|
20
14
|
const organizations_1 = require("./organizations");
|
|
21
15
|
const username_1 = require("./username");
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
exports.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
exports.accountKindSchema = zod_1.z.enum(exports.ACCOUNT_KINDS);
|
|
42
|
-
exports.CHILD_ACCOUNT_KINDS = [
|
|
43
|
-
'organization',
|
|
44
|
-
'project',
|
|
45
|
-
'bot',
|
|
46
|
-
'channel',
|
|
47
|
-
];
|
|
48
|
-
exports.childAccountKindSchema = zod_1.z.enum(exports.CHILD_ACCOUNT_KINDS);
|
|
49
|
-
/**
|
|
50
|
-
* Whether an account of this kind may be the SUBJECT OF A DELEGATION — an
|
|
51
|
-
* application acting as it on some person's authority. `POST /internal/accounts/
|
|
52
|
-
* :id/service-switch` and the OAuth delegated subject both gate on this.
|
|
53
|
-
*
|
|
54
|
-
* It is NOT the question an account switcher asks. See
|
|
55
|
-
* {@link isOperatorSwitchTargetKind}, and the note below on why the difference
|
|
56
|
-
* is `bot`.
|
|
57
|
-
*
|
|
58
|
-
* Two kinds are refused, for opposite reasons:
|
|
59
|
-
*
|
|
60
|
-
* - `personal` is a human login, so assuming it would be impersonation.
|
|
61
|
-
* - `channel` is a CONTENT identity, not an operating one. A channel exists so
|
|
62
|
-
* that posts can be authored BY it; it is never a seat anybody occupies. Its
|
|
63
|
-
* operators act on it through their own membership, and an application
|
|
64
|
-
* publishes to it with its own credential. Refusing act-as is what makes
|
|
65
|
-
* "no login, ever" structural rather than incidental: no session can be
|
|
66
|
-
* minted whose subject is a channel, so no bearer exists that could add an
|
|
67
|
-
* auth method to one (every auth-method write resolves its target from the
|
|
68
|
-
* authenticated subject, never from a parameter).
|
|
69
|
-
*
|
|
70
|
-
* Consumers must gate on this predicate rather than testing `kind === 'personal'`,
|
|
71
|
-
* which silently admits every kind added after it was written.
|
|
72
|
-
*
|
|
73
|
-
* Being act-as-eligible is NOT being without an identity of one's own. A bot is
|
|
74
|
-
* act-as-eligible AND its own actor (`accountKindActorNature` → `'agent'` in
|
|
75
|
-
* `accountSubject.ts`): an application acting as it on a person's authority
|
|
76
|
-
* records that person as the actor, and the bot acting with nobody operating it
|
|
77
|
-
* records the bot. Neither ever records the bot's owner in the bot's place.
|
|
78
|
-
*/
|
|
79
|
-
function isDelegatedActAsEligibleKind(kind) {
|
|
80
|
-
return kind === 'organization' || kind === 'project' || kind === 'bot';
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Whether a PERSON may switch into an account of this kind — become it, in an
|
|
84
|
-
* account switcher, for the rest of their session.
|
|
85
|
-
*
|
|
86
|
-
* ## Why this is not the same question as {@link isDelegatedActAsEligibleKind}
|
|
87
|
-
*
|
|
88
|
-
* The two differ on exactly one kind, `bot`, and that difference is the whole
|
|
89
|
-
* reason both exist.
|
|
90
|
-
*
|
|
91
|
-
* **A bot is not something you become. It is somebody of its own.** It is an
|
|
92
|
-
* agent's identity, with its own resources, roles, plan and balance, and it is
|
|
93
|
-
* the actor of what it does unoperated. A person may still act AS it on their
|
|
94
|
-
* own authority — that is delegation, recorded with the person as actor, and it
|
|
95
|
-
* is what {@link isDelegatedActAsEligibleKind} admits it for. What a person
|
|
96
|
-
* never does is occupy its seat. This is a refusal of a SEAT, not a capability
|
|
97
|
-
* restriction: nothing a bot may do depends on this predicate.
|
|
98
|
-
*
|
|
99
|
-
* Handing a person the bot's seat instead inverts that. It puts a human inside
|
|
100
|
-
* the identity that exists to act without one, and it does so on the human's own
|
|
101
|
-
* device, next to their personal login — which is precisely what happened: a
|
|
102
|
-
* `bot` account held a live session on a person's device, offered to them by a
|
|
103
|
-
* switcher that had asked the delegation question by mistake.
|
|
104
|
-
*
|
|
105
|
-
* `channel` is refused here as well, for the reason set out above, and
|
|
106
|
-
* `personal` because assuming somebody else's login is impersonation.
|
|
107
|
-
*
|
|
108
|
-
* ## This is the narrower predicate, deliberately
|
|
109
|
-
*
|
|
110
|
-
* Everything a person may become, a service may also act as; the reverse does
|
|
111
|
-
* not hold. A caller that is unsure which question it is asking wants THIS one:
|
|
112
|
-
* being wrong here withholds an affordance, while being wrong the other way
|
|
113
|
-
* hands out a seat.
|
|
114
|
-
*/
|
|
115
|
-
function isOperatorSwitchTargetKind(kind) {
|
|
116
|
-
return kind === 'organization' || kind === 'project';
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Narrow an unknown value to an {@link AccountKind}.
|
|
120
|
-
*
|
|
121
|
-
* The user-DTO serializers read from structurally-permissive `unknown` sources
|
|
122
|
-
* (a Drizzle row, a raw document, an already-formatted object), so each one
|
|
123
|
-
* would otherwise hand-roll this check and they would drift on what counts.
|
|
124
|
-
*/
|
|
125
|
-
function isAccountKind(value) {
|
|
126
|
-
return typeof value === 'string' && exports.ACCOUNT_KINDS.includes(value);
|
|
127
|
-
}
|
|
128
|
-
// ===========================================================================
|
|
129
|
-
// Account categories
|
|
130
|
-
//
|
|
131
|
-
// Four rules govern this taxonomy. Each one is here because the obvious
|
|
132
|
-
// alternative fails silently rather than loudly.
|
|
133
|
-
//
|
|
134
|
-
// 1. AN ID IS AN OPAQUE, IMMUTABLE SLUG — the LABEL is not stored anywhere.
|
|
135
|
-
// Every value below is an identifier that no rename may ever change. The
|
|
136
|
-
// human-readable label lives in each client's own translation catalogue,
|
|
137
|
-
// keyed by the id. Re-labelling `agency` from "Real estate agency" to
|
|
138
|
-
// "Agency" is therefore a one-line locale edit that touches no row; moving
|
|
139
|
-
// the label into the column or the DTO would make the same edit a data
|
|
140
|
-
// migration, and would pin every reader to the language of whoever chose it.
|
|
141
|
-
//
|
|
142
|
-
// 2. THE PRIMARY CATEGORY IS THE FIRST ELEMENT of an ordered list. Not a
|
|
143
|
-
// separate flag, and not a second field: a flag admits two primaries and
|
|
144
|
-
// admits none, and ordering makes both unrepresentable. The cost is that
|
|
145
|
-
// ORDER IS DATA — anything that re-serializes, sorts or de-duplicates this
|
|
146
|
-
// list can change which category is primary without erroring, so no layer
|
|
147
|
-
// between the column and the client may reorder it.
|
|
148
|
-
//
|
|
149
|
-
// 3. THE VOCABULARY IS APPEND-ONLY. `ACCOUNT_CATEGORY_IDS` may gain ids and may
|
|
150
|
-
// never lose one, because rows already carry the ids it holds. Withdrawing a
|
|
151
|
-
// category means listing it in {@link RETIRED_ACCOUNT_CATEGORY_IDS}, which
|
|
152
|
-
// removes it from the picker while leaving it readable and re-writable. The
|
|
153
|
-
// database enforces the same asymmetry: its CHECK is re-evaluated on EVERY
|
|
154
|
-
// update to a row, so narrowing the allowed set makes an unrelated write —
|
|
155
|
-
// saving a bio — fail on any account that had picked the withdrawn value.
|
|
156
|
-
// Measured on a real Postgres, `NOT VALID` included; it does not help.
|
|
157
|
-
//
|
|
158
|
-
// 4. THE SET IS CLOSED. An id nobody can validate is an id no client can render:
|
|
159
|
-
// the label comes from a translation key derived from the id, so an invented
|
|
160
|
-
// value paints as a blank or a raw slug in every app at once. Closing it also
|
|
161
|
-
// costs nothing that rule 3 does not already charge — adding a category needs
|
|
162
|
-
// a migration to widen the CHECK whether or not the enum exists, so an open
|
|
163
|
-
// list would buy back no work, only the validation.
|
|
164
|
-
// ===========================================================================
|
|
165
|
-
/**
|
|
166
|
-
* Every account category, by stable id.
|
|
167
|
-
*
|
|
168
|
-
* Grouped by comment for readability only; the storage, the wire and the picker
|
|
169
|
-
* all treat this as one flat list. `other` is the escape hatch for an account
|
|
170
|
-
* that fits nothing here.
|
|
171
|
-
*
|
|
172
|
-
* TO ADD ONE: append an id (lowercase ASCII, `snake_case`) here, publish
|
|
173
|
-
* `@oxy.so/contracts`, then ship a migration that widens
|
|
174
|
-
* `users_account_categories_check` — never edit an existing migration — and add
|
|
175
|
-
* an `accounts.accountCategory.<id>` label to each client's locales.
|
|
176
|
-
*
|
|
177
|
-
* TO WITHDRAW ONE: leave the id here and add it to
|
|
178
|
-
* {@link RETIRED_ACCOUNT_CATEGORY_IDS}. See rule 3 above.
|
|
179
|
-
*/
|
|
180
|
-
exports.ACCOUNT_CATEGORY_IDS = [
|
|
181
|
-
// ---- media & public information -----------------------------------------
|
|
182
|
-
'news',
|
|
183
|
-
'politics',
|
|
184
|
-
// ---- business & economy --------------------------------------------------
|
|
185
|
-
'business',
|
|
186
|
-
'startup',
|
|
187
|
-
'finance',
|
|
188
|
-
'crypto',
|
|
189
|
-
'marketplace',
|
|
190
|
-
'retail',
|
|
191
|
-
// The four ids the single-valued `organizationCategory` field used to hold,
|
|
192
|
-
// carried forward VERBATIM. Their labels may be rewritten freely; their ids
|
|
193
|
-
// may not, because live rows hold them.
|
|
194
|
-
'real_estate',
|
|
195
|
-
'agency',
|
|
196
|
-
'landlord',
|
|
197
|
-
'cooperative',
|
|
198
|
-
'architecture',
|
|
199
|
-
// ---- technology ----------------------------------------------------------
|
|
200
|
-
'technology',
|
|
201
|
-
'software',
|
|
202
|
-
'ai',
|
|
203
|
-
'security',
|
|
204
|
-
'automation',
|
|
205
|
-
// ---- knowledge -----------------------------------------------------------
|
|
206
|
-
'science',
|
|
207
|
-
'education',
|
|
208
|
-
'books',
|
|
209
|
-
// ---- health --------------------------------------------------------------
|
|
210
|
-
'health',
|
|
211
|
-
'fitness',
|
|
212
|
-
// ---- sport & play --------------------------------------------------------
|
|
213
|
-
'sports',
|
|
214
|
-
'gaming',
|
|
215
|
-
// ---- culture & entertainment ---------------------------------------------
|
|
216
|
-
//
|
|
217
|
-
// There is deliberately NO generic `entertainment` here, and re-adding one is
|
|
218
|
-
// a regression rather than a gap. It is the only id this list ever carried
|
|
219
|
-
// that was dominated by its own specifics — `film`, `music`, `gaming` and
|
|
220
|
-
// `comedy` all exist — and a generic drawer sitting beside its four
|
|
221
|
-
// concretions collects the lazy pick, which degrades the data for all four at
|
|
222
|
-
// once: the accounts that would have said `film` say `entertainment` instead,
|
|
223
|
-
// and `film` stops meaning what it meant.
|
|
224
|
-
//
|
|
225
|
-
// The other overlaps in this vocabulary are NOT the same case and must not be
|
|
226
|
-
// merged on this reasoning: `sports`/`fitness`, `art`/`photography`,
|
|
227
|
-
// `business`/`startup`, `finance`/`crypto`, `home_garden`/`diy` and
|
|
228
|
-
// `technology`/`software`/`security` are genuinely different audiences, and
|
|
229
|
-
// with a cap of four the granularity is cheap.
|
|
230
|
-
'music',
|
|
231
|
-
'film',
|
|
232
|
-
'podcast',
|
|
233
|
-
'art',
|
|
234
|
-
'photography',
|
|
235
|
-
'comedy',
|
|
236
|
-
// ---- everyday life -------------------------------------------------------
|
|
237
|
-
'food',
|
|
238
|
-
'travel',
|
|
239
|
-
'fashion',
|
|
240
|
-
'home_garden',
|
|
241
|
-
'diy',
|
|
242
|
-
'automotive',
|
|
243
|
-
'animals',
|
|
244
|
-
'family',
|
|
245
|
-
// ---- society -------------------------------------------------------------
|
|
246
|
-
'nonprofit',
|
|
247
|
-
'government',
|
|
248
|
-
'community',
|
|
249
|
-
'activism',
|
|
250
|
-
'environment',
|
|
251
|
-
'religion',
|
|
252
|
-
// ---- fallback ------------------------------------------------------------
|
|
253
|
-
'other',
|
|
254
|
-
];
|
|
16
|
+
// The Zod-free half of this contract lives in `./client/` (`@oxy.so/contracts/client`);
|
|
17
|
+
// it is re-exported here so the root entry is unchanged.
|
|
18
|
+
const accountGraph_1 = require("./client/accountGraph");
|
|
19
|
+
var accountGraph_2 = require("./client/accountGraph");
|
|
20
|
+
Object.defineProperty(exports, "ACCOUNT_KINDS", { enumerable: true, get: function () { return accountGraph_2.ACCOUNT_KINDS; } });
|
|
21
|
+
Object.defineProperty(exports, "CHILD_ACCOUNT_KINDS", { enumerable: true, get: function () { return accountGraph_2.CHILD_ACCOUNT_KINDS; } });
|
|
22
|
+
Object.defineProperty(exports, "isDelegatedActAsEligibleKind", { enumerable: true, get: function () { return accountGraph_2.isDelegatedActAsEligibleKind; } });
|
|
23
|
+
Object.defineProperty(exports, "isOperatorSwitchTargetKind", { enumerable: true, get: function () { return accountGraph_2.isOperatorSwitchTargetKind; } });
|
|
24
|
+
Object.defineProperty(exports, "isAccountKind", { enumerable: true, get: function () { return accountGraph_2.isAccountKind; } });
|
|
25
|
+
Object.defineProperty(exports, "ACCOUNT_CATEGORY_IDS", { enumerable: true, get: function () { return accountGraph_2.ACCOUNT_CATEGORY_IDS; } });
|
|
26
|
+
Object.defineProperty(exports, "RETIRED_ACCOUNT_CATEGORY_IDS", { enumerable: true, get: function () { return accountGraph_2.RETIRED_ACCOUNT_CATEGORY_IDS; } });
|
|
27
|
+
Object.defineProperty(exports, "isSelectableAccountCategoryId", { enumerable: true, get: function () { return accountGraph_2.isSelectableAccountCategoryId; } });
|
|
28
|
+
Object.defineProperty(exports, "SELECTABLE_ACCOUNT_CATEGORY_IDS", { enumerable: true, get: function () { return accountGraph_2.SELECTABLE_ACCOUNT_CATEGORY_IDS; } });
|
|
29
|
+
Object.defineProperty(exports, "newlyAddedRetiredCategories", { enumerable: true, get: function () { return accountGraph_2.newlyAddedRetiredCategories; } });
|
|
30
|
+
Object.defineProperty(exports, "MAX_ACCOUNT_CATEGORIES", { enumerable: true, get: function () { return accountGraph_2.MAX_ACCOUNT_CATEGORIES; } });
|
|
31
|
+
Object.defineProperty(exports, "ACCOUNT_CATEGORY_KINDS", { enumerable: true, get: function () { return accountGraph_2.ACCOUNT_CATEGORY_KINDS; } });
|
|
32
|
+
Object.defineProperty(exports, "kindAcceptsAccountCategories", { enumerable: true, get: function () { return accountGraph_2.kindAcceptsAccountCategories; } });
|
|
33
|
+
exports.accountKindSchema = zod_1.z.enum(accountGraph_1.ACCOUNT_KINDS);
|
|
34
|
+
exports.childAccountKindSchema = zod_1.z.enum(accountGraph_1.CHILD_ACCOUNT_KINDS);
|
|
255
35
|
/**
|
|
256
36
|
* Accepts EVERY id, withdrawn ones included — see rule 3.
|
|
257
37
|
*
|
|
@@ -260,60 +40,7 @@ exports.ACCOUNT_CATEGORY_IDS = [
|
|
|
260
40
|
* picked one could no longer save its bio either. That is the same failure the
|
|
261
41
|
* nullable `bio` / `avatar` fix addressed, wearing a different hat.
|
|
262
42
|
*/
|
|
263
|
-
exports.accountCategoryIdSchema = zod_1.z.enum(
|
|
264
|
-
/**
|
|
265
|
-
* Ids withdrawn from the picker. Empty today.
|
|
266
|
-
*
|
|
267
|
-
* A withdrawn id keeps working everywhere it is already stored: it validates,
|
|
268
|
-
* it survives a round-trip save, it still renders from its label key, and it
|
|
269
|
-
* stays PRIMARY if it was primary. Nothing rewrites a stored list — a read-time
|
|
270
|
-
* or migration-time demotion would silently replace a choice its owner made,
|
|
271
|
-
* which is precisely what stable ids exist to prevent. The owner drops it on
|
|
272
|
-
* their next edit; until then it is honoured.
|
|
273
|
-
*
|
|
274
|
-
* What withdrawal changes is only this: the id leaves
|
|
275
|
-
* {@link SELECTABLE_ACCOUNT_CATEGORY_IDS}, so no picker offers it, and
|
|
276
|
-
* {@link newlyAddedRetiredCategories} refuses to let a write ADD it to an
|
|
277
|
-
* account that did not already have it.
|
|
278
|
-
*/
|
|
279
|
-
exports.RETIRED_ACCOUNT_CATEGORY_IDS = [];
|
|
280
|
-
/** Whether a category may still be OFFERED. A stored one is readable either way. */
|
|
281
|
-
function isSelectableAccountCategoryId(id) {
|
|
282
|
-
return !exports.RETIRED_ACCOUNT_CATEGORY_IDS.includes(id);
|
|
283
|
-
}
|
|
284
|
-
/** The ids a picker may offer, in declaration order. */
|
|
285
|
-
exports.SELECTABLE_ACCOUNT_CATEGORY_IDS = exports.ACCOUNT_CATEGORY_IDS.filter(isSelectableAccountCategoryId);
|
|
286
|
-
/**
|
|
287
|
-
* Which of `next` are withdrawn ids the account did not already carry — i.e.
|
|
288
|
-
* the ones a write must be refused for.
|
|
289
|
-
*
|
|
290
|
-
* `retired` is a parameter rather than a module read so the rule can be
|
|
291
|
-
* exercised against a non-empty set while the production one is empty; a test
|
|
292
|
-
* over `RETIRED_ACCOUNT_CATEGORY_IDS` alone would pass vacuously today and stay
|
|
293
|
-
* passing if the rule were deleted.
|
|
294
|
-
*/
|
|
295
|
-
function newlyAddedRetiredCategories(next, previous, retired) {
|
|
296
|
-
return next.filter((id) => retired.includes(id) && !previous.includes(id));
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* How many categories one account may carry.
|
|
300
|
-
*
|
|
301
|
-
* Four, not "as many as you like". Three reasons, in the order they bind:
|
|
302
|
-
*
|
|
303
|
-
* - The primary has to MEAN something. At ten categories the first element
|
|
304
|
-
* reads as a sort artifact rather than a choice, and rule 2 above is the
|
|
305
|
-
* entire mechanism by which a primary exists.
|
|
306
|
-
* - The profile RENDERS them as a row of chips; four labels of this length is
|
|
307
|
-
* what fits a phone-width profile header before the row wraps or truncates.
|
|
308
|
-
* - Four is enough to place a genuinely compound account without a tag cloud:
|
|
309
|
-
* a housing cooperative that is also a non-profit serving a local community
|
|
310
|
-
* spends `cooperative`, `nonprofit`, `community`, `real_estate` — and is the
|
|
311
|
-
* most compound real example in the ecosystem.
|
|
312
|
-
*
|
|
313
|
-
* One constant, read by the wire schema, the database CHECK and the picker, so
|
|
314
|
-
* changing it is one edit plus a migration.
|
|
315
|
-
*/
|
|
316
|
-
exports.MAX_ACCOUNT_CATEGORIES = 4;
|
|
43
|
+
exports.accountCategoryIdSchema = zod_1.z.enum(accountGraph_1.ACCOUNT_CATEGORY_IDS);
|
|
317
44
|
/**
|
|
318
45
|
* An account's categories on the wire. ORDER IS MEANINGFUL — index 0 is the
|
|
319
46
|
* primary (rule 2).
|
|
@@ -326,7 +53,7 @@ exports.MAX_ACCOUNT_CATEGORIES = 4;
|
|
|
326
53
|
*/
|
|
327
54
|
exports.accountCategoriesSchema = zod_1.z
|
|
328
55
|
.array(exports.accountCategoryIdSchema)
|
|
329
|
-
.max(
|
|
56
|
+
.max(accountGraph_1.MAX_ACCOUNT_CATEGORIES)
|
|
330
57
|
.superRefine((ids, ctx) => {
|
|
331
58
|
const seen = new Set();
|
|
332
59
|
ids.forEach((id, index) => {
|
|
@@ -340,31 +67,6 @@ exports.accountCategoriesSchema = zod_1.z
|
|
|
340
67
|
seen.add(id);
|
|
341
68
|
});
|
|
342
69
|
});
|
|
343
|
-
/**
|
|
344
|
-
* Kinds that may carry categories: every kind EXCEPT `personal`.
|
|
345
|
-
*
|
|
346
|
-
* A person has interests, not a sector — and their interests are not a
|
|
347
|
-
* classification anybody else gets to read off their profile. Spelled out
|
|
348
|
-
* positively, like {@link isDelegatedActAsEligibleKind} and for the same reason: a `kind
|
|
349
|
-
* !== 'personal'` test silently admits every kind invented after it was
|
|
350
|
-
* written, whereas this list forces whoever adds one to decide.
|
|
351
|
-
*/
|
|
352
|
-
exports.ACCOUNT_CATEGORY_KINDS = [
|
|
353
|
-
'organization',
|
|
354
|
-
'project',
|
|
355
|
-
'bot',
|
|
356
|
-
'channel',
|
|
357
|
-
];
|
|
358
|
-
/**
|
|
359
|
-
* Whether an account of this kind may carry categories.
|
|
360
|
-
*
|
|
361
|
-
* The API refuses the write and the `users_account_categories_kind_check`
|
|
362
|
-
* constraint makes it unrepresentable; both derive from
|
|
363
|
-
* {@link ACCOUNT_CATEGORY_KINDS}, so they cannot disagree.
|
|
364
|
-
*/
|
|
365
|
-
function kindAcceptsAccountCategories(kind) {
|
|
366
|
-
return exports.ACCOUNT_CATEGORY_KINDS.includes(kind ?? '');
|
|
367
|
-
}
|
|
368
70
|
/**
|
|
369
71
|
* An account's name on the create/update wire.
|
|
370
72
|
*
|
package/dist/cjs/agentKeys.js
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.agentKeyListResponseSchema = exports.
|
|
3
|
+
exports.agentKeyListResponseSchema = exports.agentKeyOperationResultSchema = exports.agentKeyOperationChallengeSchema = exports.executeAgentKeyOperationSchema = exports.agentKeyOperationProofSchema = exports.agentKeyOperationSchema = exports.agentVerifyRequestSchema = exports.agentChallengeRequestSchema = exports.agentSignatureSchema = exports.agentProofClaimsSchema = exports.ACCOUNT_AUTH_METHODS = exports.AGENT_PROOF_ACTIONS = exports.AGENT_PROOF_TTL_MS = exports.AGENT_PROOF_AUDIENCE = void 0;
|
|
4
4
|
exports.buildAgentProofMessage = buildAgentProofMessage;
|
|
5
5
|
/** Autonomous runtime proof. No private key crosses this contract. */
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
const signIn_1 = require("./signIn");
|
|
8
8
|
const identityProof_1 = require("./identityProof");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
];
|
|
9
|
+
// The Zod-free half of this contract lives in `./client/` (`@oxy.so/contracts/client`);
|
|
10
|
+
// it is re-exported here so the root entry is unchanged.
|
|
11
|
+
const agentKeys_1 = require("./client/agentKeys");
|
|
12
|
+
var agentKeys_2 = require("./client/agentKeys");
|
|
13
|
+
Object.defineProperty(exports, "AGENT_PROOF_AUDIENCE", { enumerable: true, get: function () { return agentKeys_2.AGENT_PROOF_AUDIENCE; } });
|
|
14
|
+
Object.defineProperty(exports, "AGENT_PROOF_TTL_MS", { enumerable: true, get: function () { return agentKeys_2.AGENT_PROOF_TTL_MS; } });
|
|
15
|
+
Object.defineProperty(exports, "AGENT_PROOF_ACTIONS", { enumerable: true, get: function () { return agentKeys_2.AGENT_PROOF_ACTIONS; } });
|
|
16
|
+
Object.defineProperty(exports, "ACCOUNT_AUTH_METHODS", { enumerable: true, get: function () { return agentKeys_2.ACCOUNT_AUTH_METHODS; } });
|
|
18
17
|
exports.agentProofClaimsSchema = zod_1.z
|
|
19
18
|
.object({
|
|
20
19
|
version: zod_1.z.literal(1),
|
|
21
|
-
audience: zod_1.z.literal(
|
|
22
|
-
action: zod_1.z.enum(
|
|
20
|
+
audience: zod_1.z.literal(agentKeys_1.AGENT_PROOF_AUDIENCE),
|
|
21
|
+
action: zod_1.z.enum(agentKeys_1.AGENT_PROOF_ACTIONS),
|
|
23
22
|
accountId: zod_1.z.string().min(1),
|
|
24
23
|
actorId: zod_1.z.string().min(1),
|
|
25
24
|
authMethodId: zod_1.z.string().nullable(),
|
|
@@ -101,7 +100,6 @@ exports.agentKeyOperationResultSchema = zod_1.z
|
|
|
101
100
|
revokedMethodIds: zod_1.z.array(zod_1.z.string()),
|
|
102
101
|
})
|
|
103
102
|
.strict();
|
|
104
|
-
exports.ACCOUNT_AUTH_METHODS = ['identity', 'agent_key'];
|
|
105
103
|
/** Public credential inventory. Never includes a proof, bearer or private key. */
|
|
106
104
|
exports.agentKeyListResponseSchema = zod_1.z
|
|
107
105
|
.object({
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Account-email constants and response checks, without Zod. Schemas: `../accountEmail.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.emailVerificationConfirmResponseCheck = exports.emailVerificationStartResponseCheck = exports.emailTicketCheck = exports.emailAddressCheck = exports.EMAIL_VERIFICATION_ERROR_CODES = exports.EMAIL_TICKET_TTL_MS = exports.EMAIL_CODE_MAX_ATTEMPTS = exports.EMAIL_CODE_TTL_MS = exports.EMAIL_CODE_LENGTH = exports.EMAIL_VERIFICATION_PURPOSES = void 0;
|
|
9
|
+
const check_1 = require("./check");
|
|
10
|
+
/**
|
|
11
|
+
* - `signup`: above.
|
|
12
|
+
* - `signin`: the code (and link) of an email sign-in (`POST /auth/signin/email/start`).
|
|
13
|
+
* - `reauth`: a signed-in person proving it is them before a sensitive step
|
|
14
|
+
* (`POST /users/me/reauth/email`): a password, an authenticator, deleting the
|
|
15
|
+
* account, linking Commons.
|
|
16
|
+
*/
|
|
17
|
+
exports.EMAIL_VERIFICATION_PURPOSES = ['signup', 'signin', 'reauth'];
|
|
18
|
+
/** Digits in a code. */
|
|
19
|
+
exports.EMAIL_CODE_LENGTH = 6;
|
|
20
|
+
/** How long a code can be confirmed. */
|
|
21
|
+
exports.EMAIL_CODE_TTL_MS = 10 * 60 * 1000;
|
|
22
|
+
/** Wrong codes before a verification is spent and a new code is needed. */
|
|
23
|
+
exports.EMAIL_CODE_MAX_ATTEMPTS = 5;
|
|
24
|
+
/** How long a confirmed code's ticket can be spent. */
|
|
25
|
+
exports.EMAIL_TICKET_TTL_MS = 15 * 60 * 1000;
|
|
26
|
+
/**
|
|
27
|
+
* Stable error codes (`error.code` in the API error body). Clients map these
|
|
28
|
+
* through their localization, never the English message.
|
|
29
|
+
*/
|
|
30
|
+
exports.EMAIL_VERIFICATION_ERROR_CODES = {
|
|
31
|
+
/** The code is wrong, or its verification expired or was spent. */
|
|
32
|
+
codeInvalid: 'EMAIL_CODE_INVALID',
|
|
33
|
+
/** Too many wrong codes: request a new one. */
|
|
34
|
+
tooManyAttempts: 'EMAIL_CODE_TOO_MANY_ATTEMPTS',
|
|
35
|
+
/** The ticket is unknown, expired, spent, or for another email or purpose. */
|
|
36
|
+
ticketInvalid: 'EMAIL_TICKET_INVALID',
|
|
37
|
+
/** A sign-up without a confirmed email. */
|
|
38
|
+
ticketRequired: 'EMAIL_TICKET_REQUIRED',
|
|
39
|
+
/** This server cannot send mail. */
|
|
40
|
+
unavailable: 'EMAIL_UNAVAILABLE',
|
|
41
|
+
};
|
|
42
|
+
/* -------------------------------------------------------------------------- */
|
|
43
|
+
/* Checks */
|
|
44
|
+
/* -------------------------------------------------------------------------- */
|
|
45
|
+
exports.emailAddressCheck = (0, check_1.string)(check_1.trim, check_1.toLowerCase, (0, check_1.minLength)(3), (0, check_1.maxLength)(254), check_1.email);
|
|
46
|
+
exports.emailTicketCheck = (0, check_1.string)(check_1.trim, (0, check_1.pattern)(/^[A-Za-z0-9_-]{43}$/, 'ticket must be 32 bytes of base64url'));
|
|
47
|
+
exports.emailVerificationStartResponseCheck = (0, check_1.exact)()((0, check_1.object)({ verificationId: (0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(64)), expiresAt: (0, check_1.number)(check_1.int, check_1.positive) }));
|
|
48
|
+
exports.emailVerificationConfirmResponseCheck = (0, check_1.exact)()((0, check_1.object)({ ticket: exports.emailTicketCheck, expiresAt: (0, check_1.number)(check_1.int, check_1.positive) }));
|