@owlmeans/viable-common 0.0.48-rc.2 → 0.0.48-rc.3

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/README.md CHANGED
@@ -15,7 +15,7 @@ the Viable platform has no use for it. The package's skills are `viable-common`
15
15
  ## Installation
16
16
 
17
17
  ```bash
18
- bun add @owlmeans/viable-common@^0.0.48-rc.2
18
+ bun add @owlmeans/viable-common@^0.0.48-rc.3
19
19
  ```
20
20
 
21
21
  ## What is in it
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/viable-common",
4
- "version": "0.0.48-rc.2",
5
- "generatedAt": "2026-10-15T10:20:01.307Z",
4
+ "version": "0.0.48-rc.3",
5
+ "generatedAt": "2026-10-16T18:05:19.010Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -6,7 +6,7 @@ description: Shared, runtime-free taxonomy for presenting OwlMeans Viable agent
6
6
 
7
7
  # Agent output presentation
8
8
 
9
- **Install:** `"@owlmeans/viable-common": "^0.0.48-rc.2"` in `dependencies`
9
+ **Install:** `"@owlmeans/viable-common": "^0.0.48-rc.3"` in `dependencies`
10
10
 
11
11
  `@owlmeans/viable-common`'s `agent/presentation.ts` owns the browser-safe vocabulary for agent
12
12
  output. Keep the server and every client on `agentPresentationHelper.classifyAgentMessage()`; consumers may refine a
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/viable-common
9
9
 
10
10
  **Layer:** Cross-cutting domain (contracts only)
11
- **Install:** `"@owlmeans/viable-common": "^0.0.48-rc.2"` in `dependencies`
11
+ **Install:** `"@owlmeans/viable-common": "^0.0.48-rc.3"` in `dependencies`
12
12
  **Subpaths:** `.` · `./slot` · `./connect` · `./convert` · `./integrity` · `./intent` · `./legal` · `./iam-console` — the barrel
13
13
  re-exports every subpath except `./intent`.
14
14
  **Runtime-free:** no `@langchain/*`, no filesystem, no Ajv at run time (a devDependency, for the
@@ -36,7 +36,7 @@ execution state and card fields name.
36
36
  | `./connect` | `ConnectTarget`, `ConnectLlm`, `ConnectHarness`, `ConnectExecutor`, `ConnectOpKind`, `ConnectProjectStatus`, `ConnectStoryStatus`, `ConnectPipelineState`, `ConnectWaitReason`, `ConnectProjectBranding` / `ConnectProjectBrandingSave` / `ConnectProjectBrandingFields` / `ConnectBrandingCredit` / `ConnectBrandingCreditBody`, the configuration contract (`ConnectScopeQuery`, `ConnectConfigScope`, `ConnectProjectConfig`, `ConnectConfigVariable`, `ConnectFrontendVariable`, `ConnectConfigValue`, `ConnectConfigSaveBody`, `CONNECT_CONFIG_*`), the organization's defaults (`ConnectOrganizationBranding(Save)`, `ConnectBrandingBackfill`), the planning-kit views (`PlanningKitView`, `ConnectKitDescribe`, `ConnectKitApplyBody`, `ConnectKitApplyResult` and their `*Schema`s), `ModelTier` + `modelTierHelper` (`tierOfRole`/`clampTier`), `ModelTask*`, `InquiryPayload` + `ConnectInquiryKind`, the session and domain-status views, the convert bodies (`ConnectConvertCreateBody`, `ConnectConvertStartBody`, `ConnectConvertProceedBody` + `ConnectConvertProceedUpdate`), `ConnectAgentLock`, `ConnectPaidGate` + `ConnectGateRef` + `ConnectEntrypointOptions`, the call collection (`CONNECT_CALL_HEADER`, `CONNECT_CALL_ACCEPT_MS`, `CONNECT_CALL_COLLECT_WAIT_SEC`, `CONNECT_CALL_LOST_MS`, `ConnectCallState`, `ConnectCallPending`, `ConnectCallResult`, `ConnectCallCollectParams` / `ConnectCallCollectQuery` and their `*Schema`s), the `Connect*` error family with `ConnectConfirmation` / `ConnectConfirmationAction`, `connectProtocols(opts)` and every `*Schema` behind them |
37
37
  | `./convert` | `ConversionStage`/`Status`/`Decision` and the `conversionStageHelper` transitions (`stageAfter`/`decisionFor`/`canEnter`), `OriginKind`/`OriginShape`/`OriginState`, `StackId` + `STACK_FAMILY`, `ArchitectureCase`, `ConvertibilityVerdict`/`ConvertibilityReason`, the census classifiers (`censusHelper` — `fileClassOf`, `sizeClassOf`, `entropyClassOf`, `binaryByExtension`), the `docs/conversion/` paths, `CONVERTED_ORIGIN_DIR`, `SOURCE_LIST_EXCLUSIONS`, `CENSUS_SKIP_DIRS`, `RELOCATE_ALWAYS_KEEP`, and the model-answer schemas the conversion asks with |
38
38
  | `./integrity` | `TargetLayout` + `TARGET_LAYOUTS`, `targetLayoutHelper` (`detectTargetLayout`, `isLegacyLayout`, `targetPackageName`), `targetIntegrityHelper.verifyTargetShape`, `TARGET_INTEGRITY_FILES`, `TARGET_PROTECTED_FILES` |
39
- | `./intent` | `intent` (the four aliases), `makeIntentProtocols(opts?)`, `intentFlow` + `IntentFlowStep` + `INTENT_PAYLOAD_REF`, `IntentStashBodySchema` / `IntentPickupBodySchema`, the `INTENT_*` constants, `IntentDraft`, `IntentExpired` (404) / `IntentThrottled` (429) |
39
+ | `./intent` | `intent` (the five aliases), `makeIntentProtocols(opts?)`, `intentFlow` + `IntentFlowStep` + `INTENT_PAYLOAD_REF`, `IntentStashBodySchema` / `IntentPickupBodySchema`, the `INTENT_*` constants (`INTENT_IMPORT_PATH`, `INTENT_IMPORT_KIND` included), `IntentDraft` / `IntentImportDraft`, `IntentExpired` (404) / `IntentThrottled` (429) |
40
40
  | `./iam-console` | The owner console's IAM contract both doors share (the browser's `back.iam`, the connector's `connect.iam`): the route params (`IamProjectParams`, `IamProjectUserParams`, `IamOrganizationParams`, `IamMemberParams`, `IamGroupParams`), `IamScoped`, the bodies (`IamDefinitionUpdate`, `IamStaffSync`, `IamAssignGrant` / `IamRevokeGrant`, `IamGrantsQuery`, `IamProjectUserInvite` / `Update`, `IamOrganizationEdit`, `IamProjectMemberInvite` / `Update`, `IamGroupCreate` / `Edit`, `IamGroupMembersChange`), the answers (`IamListResponse` + `external`, `IamUsersResponse`, `IamPermissionsResponse` + `IamTenancy`, …, `IamStaffSyncResponse`), every `Iam*Schema` (with `IamScopedSchema`, `IamGroupRefSchema`), `IAM_REFUSED`, and the `@owlmeans/iam` vocabulary re-exported (`IamDefaultClass`, `IamGrantMode`, `IamGrantOrigin`, `IamRemovalPolicy`, `IAM_AREAS`, `IAM_MEMBERS_GROUP`, the record types). The refusal's CLASS (`IamRefused`, 409) is the platform's |
41
41
  | `./legal` | `OWLMEANS_LEGAL_DATES`, `LegalDocumentDates`, `PendingLegalDocumentDates`, `LegalDocumentDateMetadata`, `LegalDocumentKey` — active dates and pending metadata for public legal sources and acceptance |
42
42
 
@@ -412,10 +412,11 @@ platform through this subpath: the site, the API services (stash and pickup may
412
412
  different ones) and the manager web agree on every address, schema and step. Platform side:
413
413
  `/intent-first`.
414
414
 
415
- - **Two guest routes and one screen, no guard, no gate, no service.** `stash` POST
415
+ - **Two guest routes and two screens, no guard, no gate, no service.** `stash` POST
416
416
  `/public/intent` (`{ prompt 1..INTENT_PROMPT_MAX (8192), consent: const true }` →
417
417
  `{ ref, expiresAt }`), `pickup` POST `/public/intent/pickup` (`{ ref }`, exactly
418
- `INTENT_REF_LENGTH` (24) Base58 → `{ prompt }`), `landing` (`frontend()` at `/start`, `sticky`).
418
+ `INTENT_REF_LENGTH` (24) Base58 → `{ prompt }`), `landing` (`frontend()` at `/start`, `sticky`) and
419
+ `importLanding` (`frontend()` at `INTENT_IMPORT_PATH` = `/start/import`, `sticky`).
419
420
  Mount the tree OUTSIDE any guarded parent (a route inherits every ancestor's guard) and fill
420
421
  `service` yourself (the site binds `landing` with `{ routeOptions: { overrides: { service } } }`,
421
422
  which also makes its `url()` absolute).
@@ -429,9 +430,17 @@ different ones) and the manager web agree on every address, schema and step. Pla
429
430
  parses it on every page load) and never `?intent=` (the login surrogate window owns it).
430
431
  - **CORS is not declared here**: the routes ride the global `origin: '*'` (no credentials);
431
432
  `makeIntentProtocols` carries a `TODO(cors)` naming the origins to keep if that is restricted.
432
- - **The browser draft is IndexedDB, per origin.** `IntentDraft` (`id`, `ref`, `prompt`,
433
- `expiresAt`) is kept by the platform's browser between pickup and decision
434
- (`INTENT_DRAFT_TTL_MS`, 24 h, checked on read).
433
+ - **The second intent — import an existing project — is a plain link, no stash.** The visitor
434
+ brings no text, so the site links straight to `importLanding` (its absolute URL is
435
+ `new URL(INTENT_IMPORT_PATH, <platform web>)`); nothing crosses but the consent linker's `owlcc`.
436
+ `intentFlow` is not walked for it: its `land` step is `/start`, and the import landing needs only
437
+ the way on after sign-in, which is `HOME` for both.
438
+ - **The browser draft is IndexedDB, per origin — ONE record slot for both intents.** `IntentDraft`
439
+ (`id`, `ref`, `prompt`, `expiresAt`) is kept between pickup and decision (`INTENT_DRAFT_TTL_MS`,
440
+ 24 h); `IntentImportDraft` (`id`, `kind: INTENT_IMPORT_KIND`, `expiresAt`) holds the import wish
441
+ for `INTENT_SUSPEND_TTL_MS` (30 min — the sign-in it rides through). The newest intent replaces the
442
+ other; a record is an import iff its `kind` says so (a prompt draft carries none). Expiry is
443
+ checked on read.
435
444
 
436
445
  ## Slot metadata keys: optional means omitted
437
446
 
@@ -18,10 +18,20 @@ export declare const intent: Readonly<{
18
18
  readonly stash: 'viable:manager-api:intent:stash';
19
19
  readonly pickup: 'viable:manager-api:intent:pickup';
20
20
  readonly landing: 'viable:manager-web:intent:landing';
21
+ readonly importLanding: 'viable:manager-web:intent:import';
21
22
  }>;
22
23
  /** Where the guest API lives, and the screen the visitor's browser is sent to. */
23
24
  export declare const INTENT_API_PATH = "/public/intent";
24
25
  export declare const INTENT_LANDING_PATH = "/start";
26
+ /**
27
+ * The second way in: the public site's "Import from GitHub" is a plain link to this screen. There
28
+ * is nothing to stash — the visitor brings no text, only the wish — so no guest API call and no
29
+ * reference; the platform records the wish in the visitor's browser and opens its import dialog on
30
+ * the home screen once they are signed in.
31
+ */
32
+ export declare const INTENT_IMPORT_PATH = "/start/import";
33
+ /** `kind` of the browser record an import wish waits in ({@link IntentImportDraft}). */
34
+ export declare const INTENT_IMPORT_KIND = "import";
25
35
  /** The flow the two sides walk. */
26
36
  export declare const INTENT_FLOW = "viable:intent";
27
37
  /**
@@ -42,7 +52,10 @@ export declare const INTENT_REF_PATTERN = "^[1-9A-HJ-NP-Za-km-z]{24}$";
42
52
  export declare const INTENT_PAYLOAD_REF = "ref";
43
53
  /** How long the visitor's draft survives in their own browser waiting for a decision. */
44
54
  export declare const INTENT_DRAFT_TTL_MS: number;
45
- /** How long a suspended landing waits while the visitor signs in or registers. */
55
+ /**
56
+ * How long a suspended landing waits while the visitor signs in or registers — and how long an
57
+ * import wish waits in the browser: it belongs to that sign-in, not to a later visit.
58
+ */
46
59
  export declare const INTENT_SUSPEND_TTL_MS: number;
47
60
  /** Steps of {@link intentFlow}, exported so a screen never spells one as a literal. */
48
61
  export declare enum IntentFlowStep {
@@ -1 +1 @@
1
- {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/intent/consts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,2FAA2F;AAC3F,eAAO,MAAM,MAAM;mBACX,gCAAgC;oBAC/B,iCAAiC;qBAChC,kCAAkC;sBACjC,mCAAmC;EACnC,CAAA;AAEX,kFAAkF;AAClF,eAAO,MAAM,eAAe,mBAAmB,CAAA;AAC/C,eAAO,MAAM,mBAAmB,WAAW,CAAA;AAE3C,mCAAmC;AACnC,eAAO,MAAM,WAAW,kBAAkB,CAAA;AAE1C;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAA;AAErC,6FAA6F;AAC7F,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAA;AACnC,eAAO,MAAM,kBAAkB,+BAA+B,CAAA;AAE9D,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,QAAQ,CAAA;AAEvC,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,QAAsB,CAAA;AAEtD,kFAAkF;AAClF,eAAO,MAAM,qBAAqB,QAAiB,CAAA;AAEnD,uFAAuF;AACvF,oBAAY,cAAc;IACxB,wDAAwD;IACxD,OAAO,YAAY;IACnB,6DAA6D;IAC7D,IAAI,SAAS;IACb,6CAA6C;IAC7C,MAAM,YAAY;IAClB,mEAAmE;IACnE,MAAM,WAAW;CAClB;AAID;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU,EAAE,WA6CxB,CAAA"}
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/intent/consts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,2FAA2F;AAC3F,eAAO,MAAM,MAAM;mBACX,gCAAgC;oBAC/B,iCAAiC;qBAChC,kCAAkC;sBACjC,mCAAmC;4BAC7B,kCAAkC;EACxC,CAAA;AAEX,kFAAkF;AAClF,eAAO,MAAM,eAAe,mBAAmB,CAAA;AAC/C,eAAO,MAAM,mBAAmB,WAAW,CAAA;AAE3C;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,kBAAkB,CAAA;AAEjD,wFAAwF;AACxF,eAAO,MAAM,kBAAkB,WAAW,CAAA;AAE1C,mCAAmC;AACnC,eAAO,MAAM,WAAW,kBAAkB,CAAA;AAE1C;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAA;AAErC,6FAA6F;AAC7F,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAA;AACnC,eAAO,MAAM,kBAAkB,+BAA+B,CAAA;AAE9D,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,QAAQ,CAAA;AAEvC,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,QAAsB,CAAA;AAEtD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAiB,CAAA;AAEnD,uFAAuF;AACvF,oBAAY,cAAc;IACxB,wDAAwD;IACxD,OAAO,YAAY;IACnB,6DAA6D;IAC7D,IAAI,SAAS;IACb,6CAA6C;IAC7C,MAAM,YAAY;IAClB,mEAAmE;IACnE,MAAM,WAAW;CAClB;AAID;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU,EAAE,WA6CxB,CAAA"}
@@ -19,10 +19,20 @@ export const intent = Object.freeze({
19
19
  stash: 'viable:manager-api:intent:stash',
20
20
  pickup: 'viable:manager-api:intent:pickup',
21
21
  landing: 'viable:manager-web:intent:landing',
22
+ importLanding: 'viable:manager-web:intent:import',
22
23
  });
23
24
  /** Where the guest API lives, and the screen the visitor's browser is sent to. */
24
25
  export const INTENT_API_PATH = '/public/intent';
25
26
  export const INTENT_LANDING_PATH = '/start';
27
+ /**
28
+ * The second way in: the public site's "Import from GitHub" is a plain link to this screen. There
29
+ * is nothing to stash — the visitor brings no text, only the wish — so no guest API call and no
30
+ * reference; the platform records the wish in the visitor's browser and opens its import dialog on
31
+ * the home screen once they are signed in.
32
+ */
33
+ export const INTENT_IMPORT_PATH = '/start/import';
34
+ /** `kind` of the browser record an import wish waits in ({@link IntentImportDraft}). */
35
+ export const INTENT_IMPORT_KIND = 'import';
26
36
  /** The flow the two sides walk. */
27
37
  export const INTENT_FLOW = 'viable:intent';
28
38
  /**
@@ -43,7 +53,10 @@ export const INTENT_REF_PATTERN = '^[1-9A-HJ-NP-Za-km-z]{24}$';
43
53
  export const INTENT_PAYLOAD_REF = 'ref';
44
54
  /** How long the visitor's draft survives in their own browser waiting for a decision. */
45
55
  export const INTENT_DRAFT_TTL_MS = 24 * 60 * 60 * 1000;
46
- /** How long a suspended landing waits while the visitor signs in or registers. */
56
+ /**
57
+ * How long a suspended landing waits while the visitor signs in or registers — and how long an
58
+ * import wish waits in the browser: it belongs to that sign-in, not to a later visit.
59
+ */
47
60
  export const INTENT_SUSPEND_TTL_MS = 30 * 60 * 1000;
48
61
  /** Steps of {@link intentFlow}, exported so a screen never spells one as a literal. */
49
62
  export var IntentFlowStep;
@@ -1 +1 @@
1
- {"version":3,"file":"consts.js","sourceRoot":"","sources":["../../src/intent/consts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../../src/intent/consts.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import type { IntentProtocolOptions, IntentProtocols } from './types.js';
2
2
  /**
3
- * Declare the intent-first hand-off: two GUEST API routes and the landing screen's address.
3
+ * Declare the intent-first hand-off: two GUEST API routes and the two landing screens' addresses —
4
+ * `/start` for a stashed prompt, `/start/import` for the wish to import an existing project.
4
5
  *
5
6
  * No guard and no gate anywhere on the API — the caller is a visitor who has no account yet — and
6
7
  * no `service` on any route: each consumer fills it in (the public site names the platform's
@@ -10,7 +11,7 @@ import type { IntentProtocolOptions, IntentProtocols } from './types.js';
10
11
  * If viable ever restricts allowed origins globally, this entrypoint must keep answering the public
11
12
  * site's origins — owlmeans.com, owlmeans.pl and, in dev/stage, `http://localhost:4321`.
12
13
  *
13
- * The landing screen is `sticky`, like the OAuth consent screens: it is an ordinary in-app screen
14
+ * The landing screens are `sticky`, like the OAuth consent screens: it is an ordinary in-app screen
14
15
  * that a visitor arrives at directly from another origin.
15
16
  */
16
17
  export declare const makeIntentProtocols: (opts?: IntentProtocolOptions) => IntentProtocols;
@@ -1 +1 @@
1
- {"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../../src/intent/entrypoints.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAC4B,qBAAqB,EAAE,eAAe,EAC7E,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,UAAU,qBAAqB,KAAQ,eAkBtE,CAAA"}
1
+ {"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../../src/intent/entrypoints.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAC4B,qBAAqB,EAAE,eAAe,EAC7E,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,UAAU,qBAAqB,KAAQ,eAsBtE,CAAA"}
@@ -1,9 +1,10 @@
1
1
  import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint';
2
2
  import { frontend, route, RouteMethod } from '@owlmeans/route';
3
- import { INTENT_API_PATH, INTENT_LANDING_PATH, intent } from './consts.js';
3
+ import { INTENT_API_PATH, INTENT_IMPORT_PATH, INTENT_LANDING_PATH, intent } from './consts.js';
4
4
  import { IntentPickupBodySchema, IntentStashBodySchema } from './schemas.js';
5
5
  /**
6
- * Declare the intent-first hand-off: two GUEST API routes and the landing screen's address.
6
+ * Declare the intent-first hand-off: two GUEST API routes and the two landing screens' addresses —
7
+ * `/start` for a stashed prompt, `/start/import` for the wish to import an existing project.
7
8
  *
8
9
  * No guard and no gate anywhere on the API — the caller is a visitor who has no account yet — and
9
10
  * no `service` on any route: each consumer fills it in (the public site names the platform's
@@ -13,7 +14,7 @@ import { IntentPickupBodySchema, IntentStashBodySchema } from './schemas.js';
13
14
  * If viable ever restricts allowed origins globally, this entrypoint must keep answering the public
14
15
  * site's origins — owlmeans.com, owlmeans.pl and, in dev/stage, `http://localhost:4321`.
15
16
  *
16
- * The landing screen is `sticky`, like the OAuth consent screens: it is an ordinary in-app screen
17
+ * The landing screens are `sticky`, like the OAuth consent screens: it is an ordinary in-app screen
17
18
  * that a visitor arrives at directly from another origin.
18
19
  */
19
20
  export const makeIntentProtocols = (opts = {}) => {
@@ -23,6 +24,7 @@ export const makeIntentProtocols = (opts = {}) => {
23
24
  stash: protocol(route(intent.stash, '/', { parent: base, method: RouteMethod.POST }), contract.request({ body: typed(IntentStashBodySchema) }, typed())),
24
25
  pickup: protocol(route(intent.pickup, '/pickup', { parent: base, method: RouteMethod.POST }), contract.request({ body: typed(IntentPickupBodySchema) }, typed())),
25
26
  landing: openProtocol(route(intent.landing, opts.landing ?? INTENT_LANDING_PATH, frontend()), { sticky: true }),
27
+ importLanding: openProtocol(route(intent.importLanding, opts.importLanding ?? INTENT_IMPORT_PATH, frontend()), { sticky: true }),
26
28
  };
27
29
  };
28
30
  //# sourceMappingURL=entrypoints.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../../src/intent/entrypoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC1E,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AAK5E;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAI,GAA0B,EAAE,EAAmB,EAAE;IACvF,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,eAAe,CAAC,CAAC,CAAA;IAE3E,OAAO;QACL,IAAI;QAEJ,KAAK,EAAE,QAAQ,CACb,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,EACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,CAAkB,qBAAqB,CAAC,EAAE,EAAE,KAAK,EAAqB,CAAC,CACtG;QAED,MAAM,EAAE,QAAQ,CACd,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,EAC3E,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,CAAmB,sBAAsB,CAAC,EAAE,EAAE,KAAK,EAAsB,CAAC,CACzG;QAED,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,mBAAmB,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;KAChH,CAAA;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../../src/intent/entrypoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC9F,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AAK5E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAI,GAA0B,EAAE,EAAmB,EAAE;IACvF,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,eAAe,CAAC,CAAC,CAAA;IAE3E,OAAO;QACL,IAAI;QAEJ,KAAK,EAAE,QAAQ,CACb,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,EACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,CAAkB,qBAAqB,CAAC,EAAE,EAAE,KAAK,EAAqB,CAAC,CACtG;QAED,MAAM,EAAE,QAAQ,CACd,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,EAC3E,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,CAAmB,sBAAsB,CAAC,EAAE,EAAE,KAAK,EAAsB,CAAC,CACzG;QAED,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,mBAAmB,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAE/G,aAAa,EAAE,YAAY,CACzB,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,kBAAkB,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CACpG;KACF,CAAA;AACH,CAAC,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import type { EntrypointProtocol, OpenRequest, OpenValue } from '@owlmeans/entrypoint';
2
2
  import type { ResourceRecord } from '@owlmeans/resource';
3
+ import type { INTENT_IMPORT_KIND } from './consts.js';
3
4
  /** What the public site sends: the prompt and the person's confirmation of its processing. */
4
5
  export interface IntentStashBody {
5
6
  prompt: string;
@@ -29,6 +30,16 @@ export interface IntentDraft extends ResourceRecord {
29
30
  prompt: string;
30
31
  expiresAt: number;
31
32
  }
33
+ /**
34
+ * The wish to import an existing project, waiting in the visitor's browser between the import
35
+ * landing and the home screen. It shares {@link IntentDraft}'s record slot, so the visitor's NEWEST
36
+ * intent is the one acted on; `kind` tells the two apart (a prompt draft carries none).
37
+ */
38
+ export interface IntentImportDraft extends ResourceRecord {
39
+ id: string;
40
+ kind: typeof INTENT_IMPORT_KIND;
41
+ expiresAt: number;
42
+ }
32
43
  /**
33
44
  * Options of {@link makeIntentProtocols}.
34
45
  */
@@ -37,6 +48,8 @@ export interface IntentProtocolOptions {
37
48
  path?: string;
38
49
  /** Path of the landing screen; defaults to `/start`. */
39
50
  landing?: string;
51
+ /** Path of the import landing screen; defaults to `/start/import`. */
52
+ importLanding?: string;
40
53
  }
41
54
  /** The intent-first hand-off tree {@link makeIntentProtocols} declares. */
42
55
  export interface IntentProtocols {
@@ -49,5 +62,7 @@ export interface IntentProtocols {
49
62
  }, IntentPickupResult>;
50
63
  /** The landing screen — `sticky`, an in-app screen a visitor reaches from another origin. */
51
64
  landing: EntrypointProtocol<OpenRequest, OpenValue>;
65
+ /** The import landing screen — `sticky` too; reached by a plain link, no stash. */
66
+ importLanding: EntrypointProtocol<OpenRequest, OpenValue>;
52
67
  }
53
68
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/intent/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,8FAA8F;AAC9F,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,0FAA0F;IAC1F,OAAO,EAAE,IAAI,CAAA;CACd;AAED,kFAAkF;AAClF,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,EAAE,EAAE,MAAM,CAAA;IACV,iGAAiG;IACjG,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IAChD,KAAK,EAAE,kBAAkB,CAAC;QAAE,IAAI,EAAE,eAAe,CAAA;KAAE,EAAE,iBAAiB,CAAC,CAAA;IACvE,MAAM,EAAE,kBAAkB,CAAC;QAAE,IAAI,EAAE,gBAAgB,CAAA;KAAE,EAAE,kBAAkB,CAAC,CAAA;IAC1E,6FAA6F;IAC7F,OAAO,EAAE,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;CACpD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/intent/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAErD,8FAA8F;AAC9F,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,0FAA0F;IAC1F,OAAO,EAAE,IAAI,CAAA;CACd;AAED,kFAAkF;AAClF,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,EAAE,EAAE,MAAM,CAAA;IACV,iGAAiG;IACjG,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,cAAc;IACvD,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,OAAO,kBAAkB,CAAA;IAC/B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IAChD,KAAK,EAAE,kBAAkB,CAAC;QAAE,IAAI,EAAE,eAAe,CAAA;KAAE,EAAE,iBAAiB,CAAC,CAAA;IACvE,MAAM,EAAE,kBAAkB,CAAC;QAAE,IAAI,EAAE,gBAAgB,CAAA;KAAE,EAAE,kBAAkB,CAAC,CAAA;IAC1E,6FAA6F;IAC7F,OAAO,EAAE,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IACnD,mFAAmF;IACnF,aAAa,EAAE,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;CAC1D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/viable-common",
3
- "version": "0.0.48-rc.2",
3
+ "version": "0.0.48-rc.3",
4
4
  "license": "MIT",
5
5
  "description": "Runtime-free contracts of the OwlMeans Viable platform — the analysis, design and metadata shapes of a generated project, its target-shape manifest, the slot command vocabulary, the connector protocol, the owner console's IAM contract and the conversion vocabulary, and the intent-first hand-off from the public site to the platform.",
6
6
  "type": "module",
@@ -89,7 +89,7 @@
89
89
  "@owlmeans/flow": "^0.1.18-rc.45",
90
90
  "@owlmeans/iam": "^0.1.18-rc.53",
91
91
  "@owlmeans/llm-common": "^0.1.18-rc.39",
92
- "@owlmeans/planning": "^0.1.18-rc.27",
92
+ "@owlmeans/planning": "^0.1.18-rc.28",
93
93
  "@owlmeans/resource": "^0.1.18-rc.40",
94
94
  "@owlmeans/route": "^0.1.18-rc.35"
95
95
  },
@@ -22,12 +22,24 @@ export const intent = Object.freeze({
22
22
  stash: 'viable:manager-api:intent:stash',
23
23
  pickup: 'viable:manager-api:intent:pickup',
24
24
  landing: 'viable:manager-web:intent:landing',
25
+ importLanding: 'viable:manager-web:intent:import',
25
26
  } as const)
26
27
 
27
28
  /** Where the guest API lives, and the screen the visitor's browser is sent to. */
28
29
  export const INTENT_API_PATH = '/public/intent'
29
30
  export const INTENT_LANDING_PATH = '/start'
30
31
 
32
+ /**
33
+ * The second way in: the public site's "Import from GitHub" is a plain link to this screen. There
34
+ * is nothing to stash — the visitor brings no text, only the wish — so no guest API call and no
35
+ * reference; the platform records the wish in the visitor's browser and opens its import dialog on
36
+ * the home screen once they are signed in.
37
+ */
38
+ export const INTENT_IMPORT_PATH = '/start/import'
39
+
40
+ /** `kind` of the browser record an import wish waits in ({@link IntentImportDraft}). */
41
+ export const INTENT_IMPORT_KIND = 'import'
42
+
31
43
  /** The flow the two sides walk. */
32
44
  export const INTENT_FLOW = 'viable:intent'
33
45
 
@@ -54,7 +66,10 @@ export const INTENT_PAYLOAD_REF = 'ref'
54
66
  /** How long the visitor's draft survives in their own browser waiting for a decision. */
55
67
  export const INTENT_DRAFT_TTL_MS = 24 * 60 * 60 * 1000
56
68
 
57
- /** How long a suspended landing waits while the visitor signs in or registers. */
69
+ /**
70
+ * How long a suspended landing waits while the visitor signs in or registers — and how long an
71
+ * import wish waits in the browser: it belongs to that sign-in, not to a later visit.
72
+ */
58
73
  export const INTENT_SUSPEND_TTL_MS = 30 * 60 * 1000
59
74
 
60
75
  /** Steps of {@link intentFlow}, exported so a screen never spells one as a literal. */
@@ -1,13 +1,14 @@
1
1
  import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint'
2
2
  import { frontend, route, RouteMethod } from '@owlmeans/route'
3
- import { INTENT_API_PATH, INTENT_LANDING_PATH, intent } from './consts.js'
3
+ import { INTENT_API_PATH, INTENT_IMPORT_PATH, INTENT_LANDING_PATH, intent } from './consts.js'
4
4
  import { IntentPickupBodySchema, IntentStashBodySchema } from './schemas.js'
5
5
  import type {
6
6
  IntentPickupBody, IntentPickupResult, IntentProtocolOptions, IntentProtocols, IntentStashBody, IntentStashResult,
7
7
  } from './types.js'
8
8
 
9
9
  /**
10
- * Declare the intent-first hand-off: two GUEST API routes and the landing screen's address.
10
+ * Declare the intent-first hand-off: two GUEST API routes and the two landing screens' addresses —
11
+ * `/start` for a stashed prompt, `/start/import` for the wish to import an existing project.
11
12
  *
12
13
  * No guard and no gate anywhere on the API — the caller is a visitor who has no account yet — and
13
14
  * no `service` on any route: each consumer fills it in (the public site names the platform's
@@ -17,7 +18,7 @@ import type {
17
18
  * If viable ever restricts allowed origins globally, this entrypoint must keep answering the public
18
19
  * site's origins — owlmeans.com, owlmeans.pl and, in dev/stage, `http://localhost:4321`.
19
20
  *
20
- * The landing screen is `sticky`, like the OAuth consent screens: it is an ordinary in-app screen
21
+ * The landing screens are `sticky`, like the OAuth consent screens: it is an ordinary in-app screen
21
22
  * that a visitor arrives at directly from another origin.
22
23
  */
23
24
  export const makeIntentProtocols = (opts: IntentProtocolOptions = {}): IntentProtocols => {
@@ -37,6 +38,10 @@ export const makeIntentProtocols = (opts: IntentProtocolOptions = {}): IntentPro
37
38
  ),
38
39
 
39
40
  landing: openProtocol(route(intent.landing, opts.landing ?? INTENT_LANDING_PATH, frontend()), { sticky: true }),
41
+
42
+ importLanding: openProtocol(
43
+ route(intent.importLanding, opts.importLanding ?? INTENT_IMPORT_PATH, frontend()), { sticky: true },
44
+ ),
40
45
  }
41
46
  }
42
47
 
@@ -1,5 +1,6 @@
1
1
  import type { EntrypointProtocol, OpenRequest, OpenValue } from '@owlmeans/entrypoint'
2
2
  import type { ResourceRecord } from '@owlmeans/resource'
3
+ import type { INTENT_IMPORT_KIND } from './consts.js'
3
4
 
4
5
  /** What the public site sends: the prompt and the person's confirmation of its processing. */
5
6
  export interface IntentStashBody {
@@ -35,6 +36,17 @@ export interface IntentDraft extends ResourceRecord {
35
36
  expiresAt: number
36
37
  }
37
38
 
39
+ /**
40
+ * The wish to import an existing project, waiting in the visitor's browser between the import
41
+ * landing and the home screen. It shares {@link IntentDraft}'s record slot, so the visitor's NEWEST
42
+ * intent is the one acted on; `kind` tells the two apart (a prompt draft carries none).
43
+ */
44
+ export interface IntentImportDraft extends ResourceRecord {
45
+ id: string
46
+ kind: typeof INTENT_IMPORT_KIND
47
+ expiresAt: number
48
+ }
49
+
38
50
  /**
39
51
  * Options of {@link makeIntentProtocols}.
40
52
  */
@@ -43,6 +55,8 @@ export interface IntentProtocolOptions {
43
55
  path?: string
44
56
  /** Path of the landing screen; defaults to `/start`. */
45
57
  landing?: string
58
+ /** Path of the import landing screen; defaults to `/start/import`. */
59
+ importLanding?: string
46
60
  }
47
61
 
48
62
  /** The intent-first hand-off tree {@link makeIntentProtocols} declares. */
@@ -52,4 +66,6 @@ export interface IntentProtocols {
52
66
  pickup: EntrypointProtocol<{ body: IntentPickupBody }, IntentPickupResult>
53
67
  /** The landing screen — `sticky`, an in-app screen a visitor reaches from another origin. */
54
68
  landing: EntrypointProtocol<OpenRequest, OpenValue>
69
+ /** The import landing screen — `sticky` too; reached by a plain link, no stash. */
70
+ importLanding: EntrypointProtocol<OpenRequest, OpenValue>
55
71
  }
@@ -8,7 +8,7 @@ import { makeFlowModel } from '@owlmeans/flow'
8
8
  import { AppType } from '@owlmeans/context'
9
9
  import { RouteMethod } from '@owlmeans/route'
10
10
  import {
11
- INTENT_PAYLOAD_REF, INTENT_PROMPT_MAX, INTENT_TTL_SECONDS, IntentExpired, IntentFlowStep,
11
+ INTENT_IMPORT_PATH, INTENT_PAYLOAD_REF, INTENT_PROMPT_MAX, INTENT_TTL_SECONDS, IntentExpired, IntentFlowStep,
12
12
  IntentPickupBodySchema, IntentStashBodySchema, IntentThrottled, intent, intentFlow, makeIntentProtocols,
13
13
  } from '../src/intent/index.js'
14
14
 
@@ -24,13 +24,14 @@ const createIdOfLength = (length: number): string =>
24
24
  describe('@owlmeans/viable-common — intent-first hand-off', () => {
25
25
  const tree = makeIntentProtocols()
26
26
 
27
- test('declares one guest base, two guest routes and a landing screen — no guard, no gate, no service', () => {
27
+ test('declares one guest base, two guest routes and two landing screens — no guard, no gate, no service', () => {
28
28
  expect(tree.base.alias).toBe(intent.base)
29
29
  expect(tree.stash.alias).toBe(intent.stash)
30
30
  expect(tree.pickup.alias).toBe(intent.pickup)
31
31
  expect(tree.landing.alias).toBe(intent.landing)
32
- expect(new Set(protocols(tree).map(protocol => protocol.alias)).size).toBe(4)
33
- for (const declaration of [tree.base, tree.stash, tree.pickup, tree.landing]) {
32
+ expect(tree.importLanding.alias).toBe(intent.importLanding)
33
+ expect(new Set(protocols(tree).map(protocol => protocol.alias)).size).toBe(5)
34
+ for (const declaration of [tree.base, tree.stash, tree.pickup, tree.landing, tree.importLanding]) {
34
35
  expect(declaration.guards ?? []).toEqual([])
35
36
  expect(declaration.gate).toBeUndefined()
36
37
  expect(declaration.route.route.service).toBeUndefined()
@@ -40,6 +41,9 @@ describe('@owlmeans/viable-common — intent-first hand-off', () => {
40
41
  expect(tree.pickup.route.route.path).toBe('/pickup')
41
42
  expect(tree.landing.route.route.path).toBe('/start')
42
43
  expect(tree.landing.route.route.type).toBe(AppType.Frontend)
44
+ expect(tree.importLanding.route.route.path).toBe(INTENT_IMPORT_PATH)
45
+ expect(tree.importLanding.route.route.type).toBe(AppType.Frontend)
46
+ expect(tree.importLanding.route.route.parent).toBeUndefined()
43
47
  expect(aliasOf(tree.stash)).toBe(intent.stash)
44
48
  })
45
49