@opencxh/domain 1.171.0 → 1.172.2
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/entities/activity/blocks.d.ts +30 -30
- package/dist/entities/activity/catalog.d.ts +63 -86
- package/dist/entities/activity/descriptor.d.ts +31 -32
- package/dist/entities/activity/index.d.ts +2 -2
- package/dist/entities/activity/preview.d.ts +7 -7
- package/dist/entities/activity/resolve.d.ts +37 -38
- package/dist/entities/activity/types.d.ts +34 -34
- package/dist/entities/ai-account/types.d.ts +3 -3
- package/dist/entities/ai-account/vendors.d.ts +25 -32
- package/dist/entities/ai-budget/types.d.ts +12 -8
- package/dist/entities/ai-conversation/types.d.ts +12 -12
- package/dist/entities/ai-profile/types.d.ts +21 -26
- package/dist/entities/ai-settings/types.d.ts +12 -13
- package/dist/entities/analytics/dashboard.d.ts +1 -1
- package/dist/entities/analytics/index.d.ts +4 -4
- package/dist/entities/analytics/source.d.ts +1 -1
- package/dist/entities/analytics/usage.d.ts +23 -28
- package/dist/entities/artifact/blocks.d.ts +54 -69
- package/dist/entities/artifact/markdown.d.ts +2 -3
- package/dist/entities/artifact/types.d.ts +47 -55
- package/dist/entities/assignment/types.d.ts +74 -88
- package/dist/entities/calendar-event/types.d.ts +1 -1
- package/dist/entities/channel/index.d.ts +1 -1
- package/dist/entities/channel/signature.d.ts +8 -9
- package/dist/entities/communication/index.d.ts +1 -1
- package/dist/entities/communication/message-template.d.ts +1 -1
- package/dist/entities/company/types.d.ts +1 -1
- package/dist/entities/contact/index.d.ts +1 -1
- package/dist/entities/contact/provider.d.ts +2 -1
- package/dist/entities/contact/types.d.ts +1 -10
- package/dist/entities/custom-field-def/types.d.ts +14 -14
- package/dist/entities/external-identity/types.d.ts +45 -50
- package/dist/entities/interaction/index.d.ts +1 -1
- package/dist/entities/interaction/types.d.ts +44 -47
- package/dist/entities/live-lens/types.d.ts +39 -44
- package/dist/entities/mcp/types.d.ts +53 -57
- package/dist/entities/memory/alias.d.ts +7 -7
- package/dist/entities/memory/browse.d.ts +21 -21
- package/dist/entities/memory/ingest.d.ts +26 -17
- package/dist/entities/memory/item.d.ts +53 -58
- package/dist/entities/memory/kind.d.ts +26 -26
- package/dist/entities/memory/query.d.ts +49 -51
- package/dist/entities/playbook/actor.d.ts +20 -19
- package/dist/entities/playbook/assignment.d.ts +54 -63
- package/dist/entities/playbook/index.d.ts +2 -2
- package/dist/entities/playbook/labels.d.ts +4 -4
- package/dist/entities/playbook/trigger-vars.d.ts +14 -15
- package/dist/entities/playbook/types.d.ts +173 -303
- package/dist/entities/resource-reminder/types.d.ts +8 -9
- package/dist/entities/scope/actor.d.ts +16 -0
- package/dist/entities/{note → scope}/index.d.ts +1 -0
- package/dist/entities/scope/scope.test.d.ts +1 -0
- package/dist/entities/scope/types.d.ts +53 -0
- package/dist/entities/task/types.d.ts +1 -1
- package/dist/entities/time-entry/duration.d.ts +11 -11
- package/dist/entities/time-entry/types.d.ts +60 -60
- package/dist/entities/time-entry/work-type.d.ts +21 -24
- package/dist/entities/topic/examples.d.ts +26 -27
- package/dist/entities/topic/scope.d.ts +11 -12
- package/dist/entities/topic/types.d.ts +28 -28
- package/dist/entities/user/types.d.ts +24 -28
- package/dist/entities/webhook/types.d.ts +6 -6
- package/dist/entities/work/keys.d.ts +25 -26
- package/dist/entities/work/ladder.d.ts +48 -52
- package/dist/entities/work/types.d.ts +109 -115
- package/dist/index.cjs +6 -6
- package/dist/index.d.ts +29 -33
- package/dist/index.js +1391 -1254
- package/dist/platform/account.d.ts +34 -38
- package/dist/platform/ai-tools.d.ts +48 -52
- package/dist/platform/api.d.ts +9 -8
- package/dist/platform/author.d.ts +7 -9
- package/dist/platform/capabilities.d.ts +3 -3
- package/dist/platform/communication.d.ts +163 -204
- package/dist/platform/context.d.ts +8 -8
- package/dist/platform/identity.d.ts +16 -19
- package/dist/platform/kernel.d.ts +1 -1
- package/dist/platform/manifest.d.ts +2 -2
- package/dist/platform/media.d.ts +13 -15
- package/dist/platform/permission.d.ts +39 -0
- package/dist/platform/permission.test.d.ts +1 -0
- package/dist/platform/presence.d.ts +30 -30
- package/dist/platform/provider.d.ts +14 -76
- package/dist/platform/resource-source.d.ts +43 -45
- package/dist/platform/resource.d.ts +17 -23
- package/dist/platform/scope.d.ts +36 -62
- package/dist/platform/services.d.ts +4 -4
- package/dist/platform/settings.d.ts +0 -14
- package/dist/platform/storage.d.ts +2 -2
- package/dist/platform/sync-source.d.ts +196 -216
- package/dist/platform/transcript-cadence.d.ts +37 -41
- package/dist/platform/ui.d.ts +6 -6
- package/dist/text/endpoint.d.ts +11 -27
- package/package.json +3 -5
- package/dist/entities/note/types.d.ts +0 -14
- package/dist/entities/shopify/index.d.ts +0 -1
- package/dist/entities/shopify/types.d.ts +0 -79
- package/dist/platform/lifecycle.d.ts +0 -13
- package/dist/platform/reactive.d.ts +0 -13
- package/dist/platform/sdk.d.ts +0 -182
- package/dist/platform/service-registry.d.ts +0 -13
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OrgTeamScope } from '../scope/types';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* A topic is a **label** on a conversation: what is this about. Nothing more.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* It once also had a knowledge side (`knowledgeSources`: urls and kb articles "belonging to this
|
|
6
|
+
* topic"). That was removed because nobody read it — the form filled it, the entity stored it, and
|
|
7
|
+
* no prompt or search did anything with it. What it promised the knowledge base now does better
|
|
8
|
+
* (hybrid RAG over *all* articles) and the memory layer alongside it (`memory_find_similar`, from
|
|
9
|
+
* real traffic). See `docs/TOPICS.md`.
|
|
10
10
|
*/
|
|
11
11
|
export interface Topic {
|
|
12
12
|
id: string;
|
|
13
13
|
organizationId: string;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Whose topic this is: `org` or `team`. A topic only one person knows cannot be read by a
|
|
16
|
+
* colleague taking over the conversation. `OrgTeamScope` says so in the type, so it is not only
|
|
17
|
+
* the write validation enforcing it.
|
|
18
18
|
*/
|
|
19
|
-
ownerScope:
|
|
19
|
+
ownerScope: OrgTeamScope;
|
|
20
20
|
name: string;
|
|
21
21
|
description: string;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
* classifier
|
|
23
|
+
* Example sentences the classification prompt receives. The only field that sharpens the
|
|
24
|
+
* classifier, and therefore the only one worth maintaining.
|
|
25
25
|
*/
|
|
26
26
|
examples: string[];
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* Suggested examples, not accepted yet. Grows by itself: every time a **person** puts this topic
|
|
29
|
+
* on a conversation or corrects it, the opening sentence lands here.
|
|
30
30
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* Deliberately next to `examples` and not in it: the classification prompt is where one bad
|
|
32
|
+
* example shifts the behaviour of *every* following conversation, and there is no undo on a
|
|
33
|
+
* prompt that sat crooked for three weeks. `examples` stays the admin's; this is a suggestion.
|
|
34
34
|
*/
|
|
35
35
|
exampleCandidates?: TopicExampleCandidate[];
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* One suggested example.
|
|
39
39
|
*
|
|
40
|
-
* `corrected`
|
|
41
|
-
*
|
|
42
|
-
*
|
|
40
|
+
* `corrected` distinguishes "someone put a topic on a conversation that had none" from "someone
|
|
41
|
+
* changed the topic" — the second is a corrected mistake and thereby the most informative case
|
|
42
|
+
* there is. The UI puts those on top.
|
|
43
43
|
*/
|
|
44
44
|
export interface TopicExampleCandidate {
|
|
45
45
|
text: string;
|
|
@@ -48,14 +48,14 @@ export interface TopicExampleCandidate {
|
|
|
48
48
|
corrected: boolean;
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
51
|
+
* How many examples a topic may carry.
|
|
52
52
|
*
|
|
53
|
-
*
|
|
54
|
-
* (`apps/ai/server/src/playbook/ai/classify.ts`),
|
|
55
|
-
* per
|
|
53
|
+
* The whole list goes into the system prompt as JSON on *every* classification
|
|
54
|
+
* (`apps/ai/server/src/playbook/ai/classify.ts`), so unlimited growth makes classifying more
|
|
55
|
+
* expensive per conversation until it no longer fits.
|
|
56
56
|
*/
|
|
57
57
|
export declare const MAX_TOPIC_EXAMPLES = 20;
|
|
58
|
-
/**
|
|
58
|
+
/** Same for the candidate list: a suggestion bucket that fills up is one nobody reviews. */
|
|
59
59
|
export declare const MAX_TOPIC_CANDIDATES = 20;
|
|
60
|
-
/**
|
|
60
|
+
/** An example is an opening sentence, not a transcript. */
|
|
61
61
|
export declare const MAX_TOPIC_EXAMPLE_CHARS = 300;
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Human or agent.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* An agent is **not a separate concept beside the user** but a user with a different type. A
|
|
5
|
+
* choice with a concrete purpose: it gets a real `userId`, so it runs through `authorizeIdentity`
|
|
6
|
+
* on the fail-closed path, it signs its activities with its own name instead of as "system", it
|
|
7
|
+
* can be a team member (`getReadableTeamIds` works), and it spends from its own per-user budget.
|
|
8
|
+
* Each of those would otherwise have been an exception, and every exception is a place where an
|
|
9
|
+
* audit loses it.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Absent means `"user"`: existing rows are humans, and the mirror is not backfilled.
|
|
12
12
|
*/
|
|
13
13
|
export type UserType = "user" | "agent";
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* What another surface may know about a user in order to **show** them.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* daar niets mee te maken heeft.
|
|
17
|
+
* Separate from {@link User}, and that is the point: looking a name up is not the same as managing
|
|
18
|
+
* a user. The admin route returns the whole record plus its roles (an extra RPC to `system.rbac`) —
|
|
19
|
+
* exactly what you do not want when only putting an author name in a timeline: it costs a call
|
|
20
|
+
* nobody needs and shares email and roles with an app that has nothing to do with them.
|
|
22
21
|
*
|
|
23
|
-
* `type`
|
|
22
|
+
* `type` *is* in here: a timeline or a participant list wants to be able to mark an agent.
|
|
24
23
|
*/
|
|
25
24
|
export interface UserProfile {
|
|
26
25
|
id: string;
|
|
@@ -29,16 +28,16 @@ export interface UserProfile {
|
|
|
29
28
|
avatarUrl?: string;
|
|
30
29
|
type?: UserType;
|
|
31
30
|
/**
|
|
32
|
-
*
|
|
31
|
+
* An agent's brain, when this is an agent — see {@link User.profileId}.
|
|
33
32
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
33
|
+
* Belongs on this compact record and not only on the full one: "is this an agent" is already
|
|
34
|
+
* here (`type`), and "with which brain" is the immediate follow-up of every caller handing it
|
|
35
|
+
* work. Without this field the ai app had to use the admin route — the whole record plus an RPC
|
|
36
|
+
* to `system.rbac` — to learn one id.
|
|
38
37
|
*/
|
|
39
38
|
profileId?: string;
|
|
40
39
|
}
|
|
41
|
-
/** Is
|
|
40
|
+
/** Is this user an agent? An absent type = human. */
|
|
42
41
|
export declare function isAgentUser(user: {
|
|
43
42
|
type?: UserType | string;
|
|
44
43
|
}): boolean;
|
|
@@ -48,16 +47,13 @@ export interface User {
|
|
|
48
47
|
email: string;
|
|
49
48
|
availableOrganizations: string[];
|
|
50
49
|
/**
|
|
51
|
-
*
|
|
50
|
+
* Human or agent. See {@link UserType}.
|
|
52
51
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
52
|
+
* Sits on the **local mirror** and not in `system.users`: that is the platform record and we do
|
|
53
|
+
* not own it. Everything that needs to know "is this a human" reads this field.
|
|
55
54
|
*/
|
|
56
55
|
type?: UserType;
|
|
57
|
-
/**
|
|
58
|
-
* Het brein van een agent: het `AIProfile` waarmee hij werkt. Alleen gezet als
|
|
59
|
-
* `type === "agent"`.
|
|
60
|
-
*/
|
|
56
|
+
/** An agent's brain: the `AIProfile` it works with. Only set when `type === "agent"`. */
|
|
61
57
|
profileId?: string;
|
|
62
58
|
/** Mirrored from system.users. */
|
|
63
59
|
firstName?: string;
|
|
@@ -19,16 +19,16 @@ export interface Webhook {
|
|
|
19
19
|
enabled: boolean;
|
|
20
20
|
createdBy: string;
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* How the last delivery went.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* Four fields and no delivery history: the question an admin asks is "does this arrive?", and
|
|
25
|
+
* that is answered by the last attempt plus a counter. A full history is a screen of its own and
|
|
26
|
+
* an entity of its own.
|
|
27
27
|
*/
|
|
28
28
|
lastDeliveryAt?: number;
|
|
29
|
-
/** HTTP
|
|
29
|
+
/** HTTP status of the last attempt. Absent = the call never reached an answer. */
|
|
30
30
|
lastStatus?: number;
|
|
31
31
|
lastError?: string;
|
|
32
|
-
/**
|
|
32
|
+
/** Consecutive failures, zero as soon as one arrives — not a running total. */
|
|
33
33
|
failureCount?: number;
|
|
34
34
|
}
|
|
@@ -1,57 +1,56 @@
|
|
|
1
1
|
import { WorkItem, WorkProject } from './types';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Keys: the scopeKeys other apps point at work with, and the human item key.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* scopeKey
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Both live in `domain` and not in the app, because they are contracts: the client builds a
|
|
6
|
+
* scopeKey to start a timer, the server authorizes it, and two places spelling the prefix out
|
|
7
|
+
* separately drift apart silently on the first typo — resulting in "no access to this scope"
|
|
8
|
+
* instead of an error saying what is wrong.
|
|
9
9
|
*/
|
|
10
|
-
/**
|
|
10
|
+
/** The scope kinds `apps/work` claims through `/provider/scope/describe`. */
|
|
11
11
|
export declare const WORK_ITEM_SCOPE_KIND = "work_item";
|
|
12
12
|
export declare const WORK_PROJECT_SCOPE_KIND = "work_project";
|
|
13
13
|
export declare function workItemScopeKey(itemId: string): string;
|
|
14
14
|
export declare function workProjectScopeKey(projectId: string): string;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* The human key: `SAL-142`, or `SAL-142-1` for a subitem.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* Only for items *with* a project — a loose item has none, and that is not an omission but the
|
|
19
|
+
* difference between "work with a place in a process" and "something I still have to do".
|
|
20
20
|
*/
|
|
21
21
|
export declare function formatItemKey(projectKey: string, sequenceNumber: number, subSequence?: number): string;
|
|
22
|
-
/**
|
|
22
|
+
/** What sits inside a `SAL-142-1`, or `null` when it is not an item key. */
|
|
23
23
|
export interface ParsedItemKey {
|
|
24
24
|
projectKey: string;
|
|
25
25
|
sequenceNumber: number;
|
|
26
26
|
subSequence?: number;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Reads a key someone typed or pasted.
|
|
30
30
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* zijn als project `SAL-142`, item `1`.
|
|
31
|
+
* Case-insensitive on the input side and normalized on the output side, because people type
|
|
32
|
+
* `sal-142` in a search field and expect their item. The project prefix is `[A-Z0-9]{2,8}`, which
|
|
33
|
+
* excludes a hyphen — otherwise `SAL-142-1` could just as well read as project `SAL-142`, item `1`.
|
|
35
34
|
*/
|
|
36
35
|
export declare function parseItemKey(input: string): ParsedItemKey | null;
|
|
37
|
-
/**
|
|
36
|
+
/** The project key belonging to a name: `"Sales pipeline"` → `"SAL"`. */
|
|
38
37
|
export declare function suggestProjectKey(name: string): string;
|
|
39
38
|
/**
|
|
40
|
-
*
|
|
39
|
+
* An item's file keys: what hours, memory and attributes find it back with.
|
|
41
40
|
*
|
|
42
|
-
* **
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
41
|
+
* **Keep it small.** This is the set of the row itself and not of its whole surroundings — these
|
|
42
|
+
* keys ride along on every authorization, including every memory write, so this item's children do
|
|
43
|
+
* not belong in it. The same trade-off `companyDossierKeys` makes against `keySetForCompany` in
|
|
44
|
+
* crm.
|
|
46
45
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* The hard upper bound is there for the pathological case: an item with two hundred parties must
|
|
47
|
+
* not put an array of two hundred keys on every authorization.
|
|
49
48
|
*/
|
|
50
49
|
export declare function itemDossierKeys(item: Pick<WorkItem, "id" | "projectId" | "ancestorKeys" | "partyKeys">, limit?: number): string[];
|
|
51
50
|
/**
|
|
52
|
-
*
|
|
51
|
+
* A project's file keys: itself only.
|
|
53
52
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
53
|
+
* A project has unbounded items, so passing its children would put an unbounded array on every
|
|
54
|
+
* authorization. Whoever wants the items asks for them.
|
|
56
55
|
*/
|
|
57
56
|
export declare function projectDossierKeys(project: Pick<WorkProject, "id">): string[];
|
|
@@ -1,97 +1,93 @@
|
|
|
1
1
|
import { WorkProject, WorkStatus, WorkStatusCategory } from './types';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* The status ladder — the only place that knows whether an item has a project.
|
|
4
4
|
*
|
|
5
|
-
* `WorkItem.projectId` is
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* en nergens anders.
|
|
5
|
+
* `WorkItem.projectId` is optional, and without discipline that means an `if (projectId)` in every
|
|
6
|
+
* list, every counter and every status picker. So anything asking "which statuses can this item
|
|
7
|
+
* have" or "is this open" goes through {@link ladderFor} and {@link categoryOf}, and nowhere else.
|
|
9
8
|
*/
|
|
10
9
|
/**
|
|
11
|
-
*
|
|
10
|
+
* The fixed ladder for work *without* a project.
|
|
12
11
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* These three keys are **reserved**: a project may not claim them, because then the same key could
|
|
13
|
+
* have a different category in two ladders and the org-wide "what is open" query would silently go
|
|
14
|
+
* wrong. `validateStatuses` guards that.
|
|
16
15
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* verdubbelen tot `work:work:status_open`.
|
|
16
|
+
* The labels are **i18n keys, not text** — a literal string here would fix the language at module
|
|
17
|
+
* level for every consumer, exactly what the i18n rule in `DESIGN_SYSTEM.md` §11 forbids. They
|
|
18
|
+
* carry no app prefix because the app-sdk adds that on lookup; a `work:` prefix here would double
|
|
19
|
+
* up to `work:work:status_open` inside the app itself.
|
|
22
20
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
21
|
+
* A project status has no key but a name an admin typed. Only these three are translatable,
|
|
22
|
+
* because only these are ours.
|
|
25
23
|
*/
|
|
26
24
|
export declare const LOOSE_STATUSES: readonly WorkStatus[];
|
|
27
|
-
/**
|
|
25
|
+
/** The keys {@link LOOSE_STATUSES} occupies. */
|
|
28
26
|
export declare const RESERVED_STATUS_KEYS: readonly string[];
|
|
29
27
|
/**
|
|
30
|
-
*
|
|
28
|
+
* The ladder that applies to this item.
|
|
31
29
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
30
|
+
* A project *without* statuses falls back to the fixed ladder instead of yielding an empty list: a
|
|
31
|
+
* status picker with zero options is a dead end, and a half-created project should not be
|
|
32
|
+
* unusable.
|
|
35
33
|
*/
|
|
36
34
|
export declare function ladderFor(project?: WorkProject | null): readonly WorkStatus[];
|
|
37
35
|
/**
|
|
38
|
-
*
|
|
36
|
+
* The category of a status key within a ladder.
|
|
39
37
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
38
|
+
* Falls back to `"todo"` on an unknown key, which is the safe side: an item pointing at a deleted
|
|
39
|
+
* status would otherwise vanish from every count as if finished. Better visible in the wrong place
|
|
40
|
+
* than invisible.
|
|
43
41
|
*/
|
|
44
42
|
export declare function categoryOf(statusKey: string, ladder: readonly WorkStatus[]): WorkStatusCategory;
|
|
45
|
-
/**
|
|
43
|
+
/** The status itself, when the ladder knows it. */
|
|
46
44
|
export declare function statusIn(statusKey: string, ladder: readonly WorkStatus[]): WorkStatus | undefined;
|
|
47
|
-
/**
|
|
45
|
+
/** Where a new item starts: the project's explicit choice, otherwise the first step. */
|
|
48
46
|
export declare function defaultStatusKey(project?: WorkProject | null): string;
|
|
49
|
-
/** `order`
|
|
47
|
+
/** `order` first, ties broken on label so the ordering is stable. */
|
|
50
48
|
export declare function sortStatuses(ladder: readonly WorkStatus[]): WorkStatus[];
|
|
51
49
|
/**
|
|
52
|
-
* Is
|
|
50
|
+
* Is this item finished? The only correct way to ask that question.
|
|
53
51
|
*
|
|
54
|
-
* `isWorkClosed`
|
|
55
|
-
*
|
|
56
|
-
* op zit te wachten.
|
|
52
|
+
* `isWorkClosed` and not `isClosed`, because `entities/interaction` already exports that name for a
|
|
53
|
+
* conversation. Two `isClosed`es in one barrel is exactly the confusion this field does not need.
|
|
57
54
|
*/
|
|
58
55
|
export declare function isWorkClosed(statusKey: string, ladder: readonly WorkStatus[]): boolean;
|
|
59
56
|
/**
|
|
60
|
-
*
|
|
57
|
+
* The status key belonging to a name: lowercase, hyphens, no accents.
|
|
61
58
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* "Béta" `beta` wordt en niet `b-ta`.
|
|
59
|
+
* Same shape and same reason as `workTypeKey` for the work types: the admin screen shows it while
|
|
60
|
+
* you type, so what the user sees there has to be exactly what the server writes.
|
|
61
|
+
* `normalize("NFD")` plus stripping the combining marks, so "Béta" becomes `beta` and not `b-ta`.
|
|
66
62
|
*/
|
|
67
63
|
export declare function workStatusKey(label: string): string;
|
|
68
64
|
/**
|
|
69
|
-
*
|
|
65
|
+
* The same key, guaranteed still free within the organisation.
|
|
70
66
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
67
|
+
* Collisions are the rule here and not the exception: keys are org-unique while statuses are
|
|
68
|
+
* managed per project, so two projects both creating a "Review" end up here. The second gets
|
|
69
|
+
* `review-2` instead of an error — an admin picking a name should not trip over a key they never
|
|
70
|
+
* saw.
|
|
75
71
|
*
|
|
76
|
-
* `taken`
|
|
77
|
-
*
|
|
72
|
+
* `taken` must also contain the keys of deleted statuses as long as items point at them, and
|
|
73
|
+
* always {@link RESERVED_STATUS_KEYS}.
|
|
78
74
|
*/
|
|
79
75
|
export declare function uniqueWorkStatusKey(label: string, taken: Iterable<string>): string;
|
|
80
|
-
/**
|
|
76
|
+
/** What is wrong with a proposed ladder, as readable reasons. */
|
|
81
77
|
export interface StatusLadderProblem {
|
|
82
|
-
/** Index in
|
|
78
|
+
/** Index in the supplied list, or `-1` when it concerns the list as a whole. */
|
|
83
79
|
index: number;
|
|
84
80
|
reason: "empty" | "duplicate_key" | "reserved_key" | "missing_key" | "no_open" | "no_done";
|
|
85
81
|
key?: string;
|
|
86
82
|
}
|
|
87
83
|
/**
|
|
88
|
-
*
|
|
84
|
+
* Validates a ladder before it is stored.
|
|
89
85
|
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
86
|
+
* Exists because the store guards nothing here: `statuses` is one embedded array, so uniqueness
|
|
87
|
+
* and completeness are the writer's responsibility. Pure and without I/O, so the admin screen can
|
|
88
|
+
* show the same rules the server enforces.
|
|
93
89
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
90
|
+
* The last two rules are not taste: a ladder without an open category marks every new item
|
|
91
|
+
* finished immediately, and a ladder without `done` makes finishing impossible.
|
|
96
92
|
*/
|
|
97
93
|
export declare function validateStatuses(statuses: readonly WorkStatus[]): StatusLadderProblem[];
|