@shipstatic/types 2.0.0 → 2.2.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/index.d.ts +116 -56
- package/dist/index.js +137 -29
- package/package.json +1 -1
- package/src/index.ts +176 -82
package/dist/index.d.ts
CHANGED
|
@@ -178,30 +178,10 @@ export interface DomainValidateResponse {
|
|
|
178
178
|
/** Error message, null when valid */
|
|
179
179
|
error: string | null;
|
|
180
180
|
}
|
|
181
|
-
/**
|
|
182
|
-
* Deployment token for automated deployments
|
|
183
|
-
*/
|
|
184
|
-
export interface Token {
|
|
185
|
-
/** 7-char management identifier */
|
|
186
|
-
readonly token: string;
|
|
187
|
-
/** The account this token belongs to */
|
|
188
|
-
readonly account: string;
|
|
189
|
-
/** SHA256 hash of the raw credential (auth lookups only, never exposed to users) */
|
|
190
|
-
readonly hash: string;
|
|
191
|
-
/** IP-lock. Non-null = single-use (claimable only from this IP, once); null = multi-use. */
|
|
192
|
-
readonly ip: string | null;
|
|
193
|
-
/** Labels for categorization and filtering (lowercase, alphanumeric with separators). Always present, empty array when none. */
|
|
194
|
-
labels: string[];
|
|
195
|
-
/** Unix timestamp (seconds) when token was created */
|
|
196
|
-
readonly created: number;
|
|
197
|
-
/** Unix timestamp (seconds) when token expires, null for never */
|
|
198
|
-
readonly expires: number | null;
|
|
199
|
-
/** Consumption timestamp. Single-use: gates re-use (set once). Multi-use: refreshed on every claim. Null = never claimed. */
|
|
200
|
-
readonly used: number | null;
|
|
201
|
-
}
|
|
202
181
|
/**
|
|
203
182
|
* Token as returned by the list endpoint.
|
|
204
|
-
*
|
|
183
|
+
* The secret is shown once at creation and never again — listings carry
|
|
184
|
+
* only the management identifier and lifecycle metadata.
|
|
205
185
|
*/
|
|
206
186
|
export interface TokenListItem {
|
|
207
187
|
/** 7-char management identifier (e.g., "a1b2c3d") */
|
|
@@ -212,7 +192,7 @@ export interface TokenListItem {
|
|
|
212
192
|
readonly created: number;
|
|
213
193
|
/** Unix timestamp (seconds) when token expires, null for never */
|
|
214
194
|
readonly expires: number | null;
|
|
215
|
-
/**
|
|
195
|
+
/** Unix timestamp (seconds) of the last request authenticated with this token, null if never used */
|
|
216
196
|
readonly used: number | null;
|
|
217
197
|
}
|
|
218
198
|
/**
|
|
@@ -281,6 +261,20 @@ export interface Account {
|
|
|
281
261
|
/** Grace period expiration (unix seconds), null if no grace period active */
|
|
282
262
|
readonly grace: number | null;
|
|
283
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Account as returned by `GET /account` — the entity plus how the request
|
|
266
|
+
* was authorized, so `whoami` can answer "what credential am I holding?".
|
|
267
|
+
* Request-scoped fields live on the response type, never on the entity
|
|
268
|
+
* (the `DeploymentCreateResponse` pattern).
|
|
269
|
+
*/
|
|
270
|
+
export interface AccountGetResponse extends Account {
|
|
271
|
+
/** How the request that produced this response was authorized. */
|
|
272
|
+
readonly authMethod: AuthMethodType;
|
|
273
|
+
/** Present (and true) only when the caller is an operator acting as themselves. */
|
|
274
|
+
readonly isAdmin?: true;
|
|
275
|
+
/** Present only during read-only admin impersonation: the operator's account id. */
|
|
276
|
+
readonly impersonatedBy?: string;
|
|
277
|
+
}
|
|
284
278
|
/**
|
|
285
279
|
* Account-specific configuration overrides
|
|
286
280
|
* Allows per-account customization of limits without changing plan
|
|
@@ -438,15 +432,14 @@ export declare class ShipError extends Error {
|
|
|
438
432
|
*/
|
|
439
433
|
export declare function isShipError(error: unknown): error is ShipError;
|
|
440
434
|
/**
|
|
441
|
-
* Plan-based platform limits returned by the `/
|
|
435
|
+
* Plan-based platform limits returned by the `/limits` endpoint.
|
|
442
436
|
*
|
|
443
437
|
* The SDK fetches these once on first API call to drive client-side
|
|
444
438
|
* file-size / file-count / total-size validation that mirrors what the API
|
|
445
439
|
* would enforce server-side. Limits vary by account plan.
|
|
446
440
|
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
* caps for the current account.
|
|
441
|
+
* These are the *platform's* posted caps for the current account — server
|
|
442
|
+
* truth delivered at runtime, never hard-coded on the client.
|
|
450
443
|
*/
|
|
451
444
|
export interface PlatformLimits {
|
|
452
445
|
/** Maximum size in bytes for a single file. */
|
|
@@ -525,6 +518,25 @@ export interface PingResponse {
|
|
|
525
518
|
/** Optional timestamp */
|
|
526
519
|
timestamp?: number;
|
|
527
520
|
}
|
|
521
|
+
/**
|
|
522
|
+
* How a request (or recorded activity) was authorized.
|
|
523
|
+
*
|
|
524
|
+
* Client populations: `SESSION` (first-party cookie), `API_KEY` (`ship-`
|
|
525
|
+
* key), `TOKEN` (`deploy-` deploy token), `AGENT` (anonymous public deploy —
|
|
526
|
+
* no credential; the platform grants the public-account identity per
|
|
527
|
+
* request), `OAUTH` (delegated access token). Server populations: `WEBHOOK`
|
|
528
|
+
* (signed webhook processing), `SYSTEM` (scheduled/background jobs).
|
|
529
|
+
*/
|
|
530
|
+
export declare const AuthMethod: {
|
|
531
|
+
readonly SESSION: "session";
|
|
532
|
+
readonly API_KEY: "apiKey";
|
|
533
|
+
readonly TOKEN: "token";
|
|
534
|
+
readonly AGENT: "agent";
|
|
535
|
+
readonly OAUTH: "oauth";
|
|
536
|
+
readonly WEBHOOK: "webhook";
|
|
537
|
+
readonly SYSTEM: "system";
|
|
538
|
+
};
|
|
539
|
+
export type AuthMethodType = typeof AuthMethod[keyof typeof AuthMethod];
|
|
528
540
|
/**
|
|
529
541
|
* Shape constants for API keys (`ship-{64 hex chars}`).
|
|
530
542
|
* Single source of truth used by validation utilities and auth middleware.
|
|
@@ -540,25 +552,76 @@ export declare const API_KEY: {
|
|
|
540
552
|
readonly HINT_LENGTH: 4;
|
|
541
553
|
};
|
|
542
554
|
/**
|
|
543
|
-
* Shape constants for deploy tokens (`
|
|
555
|
+
* Shape constants for deploy tokens (`deploy-{64 hex chars}`).
|
|
544
556
|
* Single source of truth used by validation utilities and auth middleware.
|
|
545
557
|
*/
|
|
546
558
|
export declare const DEPLOY_TOKEN: {
|
|
547
559
|
/** Prefix that identifies a deploy token. */
|
|
548
|
-
readonly PREFIX: "
|
|
560
|
+
readonly PREFIX: "deploy-";
|
|
549
561
|
/** Number of hex characters following the prefix. */
|
|
550
562
|
readonly HEX_LENGTH: 64;
|
|
551
|
-
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH =
|
|
552
|
-
readonly TOTAL_LENGTH:
|
|
563
|
+
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 71`). */
|
|
564
|
+
readonly TOTAL_LENGTH: 71;
|
|
553
565
|
};
|
|
554
|
-
|
|
555
|
-
|
|
566
|
+
/**
|
|
567
|
+
* Shape constants for caller identifiers (the `X-Caller` instance-identity
|
|
568
|
+
* header — rate-limit bucketing for multi-tenant orchestrators). The API
|
|
569
|
+
* normalizes case and silently ignores malformed values (the header is
|
|
570
|
+
* unauthenticated); clients validate at the boundary via `validateCaller`,
|
|
571
|
+
* so a value the server would drop fails fast instead.
|
|
572
|
+
*/
|
|
573
|
+
export declare const CALLER: {
|
|
574
|
+
/** HTTP header name. */
|
|
575
|
+
readonly HEADER: "X-Caller";
|
|
576
|
+
/** Maximum identifier length. */
|
|
577
|
+
readonly MAX_LENGTH: 128;
|
|
578
|
+
/** Allowed characters: alphanumeric, dot, underscore, hyphen. */
|
|
579
|
+
readonly PATTERN: RegExp;
|
|
580
|
+
};
|
|
581
|
+
/**
|
|
582
|
+
* Token populations distinguishable by shape. The platform carries every
|
|
583
|
+
* client token in one wire slot (`Authorization: Bearer <value>`) and
|
|
584
|
+
* classifies by value, never by a side channel — this is the classifier.
|
|
585
|
+
*
|
|
586
|
+
* `API_KEY` and `DEPLOY_TOKEN` *are* `AuthMethod.API_KEY` and
|
|
587
|
+
* `AuthMethod.TOKEN` — the equality is structural, so a classification flows
|
|
588
|
+
* straight into an auth method and the pair can never drift. `OPAQUE` is any
|
|
589
|
+
* other value — shape says nothing about it, so only a lookup can. Today the
|
|
590
|
+
* server refuses every opaque bearer; the OAuth access-token population
|
|
591
|
+
* resolves there when the authorization server ships.
|
|
592
|
+
*/
|
|
593
|
+
export declare const TokenKind: {
|
|
556
594
|
readonly API_KEY: "apiKey";
|
|
557
|
-
readonly
|
|
558
|
-
readonly
|
|
559
|
-
readonly SYSTEM: "system";
|
|
595
|
+
readonly DEPLOY_TOKEN: "token";
|
|
596
|
+
readonly OPAQUE: "opaque";
|
|
560
597
|
};
|
|
561
|
-
export type
|
|
598
|
+
export type TokenKindType = typeof TokenKind[keyof typeof TokenKind];
|
|
599
|
+
/**
|
|
600
|
+
* Classify a client token by shape. The single dispatch used by both sides
|
|
601
|
+
* of the wire: API auth middleware (which population is this credential?)
|
|
602
|
+
* and SDK validation (which format rules apply before sending?). Sharing it
|
|
603
|
+
* is what guarantees client and server can never disagree on dispatch.
|
|
604
|
+
*/
|
|
605
|
+
export declare function classifyToken(token: string): TokenKindType;
|
|
606
|
+
/**
|
|
607
|
+
* OAuth scope vocabulary for delegated third-party access tokens.
|
|
608
|
+
* Single source of truth used by the authorization server (advertised in
|
|
609
|
+
* `scopes_supported`), the API's scope-enforcement middleware, and consent UI
|
|
610
|
+
* copy. The standard `offline_access` scope (refresh tokens) is not platform
|
|
611
|
+
* vocabulary and is deliberately absent — the middleware never checks it.
|
|
612
|
+
*
|
|
613
|
+
* Deliberately absent by design: any `tokens:*` scope, `account:write`, or
|
|
614
|
+
* admin scope — a delegated app must never mint credentials, delete the
|
|
615
|
+
* account, or act as admin.
|
|
616
|
+
*/
|
|
617
|
+
export declare const OAuthScope: {
|
|
618
|
+
readonly ACCOUNT_READ: "account:read";
|
|
619
|
+
readonly DEPLOYMENTS_READ: "deployments:read";
|
|
620
|
+
readonly DEPLOYMENTS_WRITE: "deployments:write";
|
|
621
|
+
readonly DOMAINS_READ: "domains:read";
|
|
622
|
+
readonly DOMAINS_WRITE: "domains:write";
|
|
623
|
+
};
|
|
624
|
+
export type OAuthScopeType = typeof OAuthScope[keyof typeof OAuthScope];
|
|
562
625
|
export declare const DEPLOYMENT_CONFIG_FILENAME = "ship.json";
|
|
563
626
|
/** Default ship.json config for SPA routing. Single source of truth — used by both API and SDK. */
|
|
564
627
|
export declare const SPA_DEFAULT_CONFIG: {
|
|
@@ -575,6 +638,19 @@ export declare function validateApiKey(apiKey: string): void;
|
|
|
575
638
|
* Validate deploy token format
|
|
576
639
|
*/
|
|
577
640
|
export declare function validateDeployToken(deployToken: string): void;
|
|
641
|
+
/**
|
|
642
|
+
* Validate a client token of any population. Classifies by shape and applies
|
|
643
|
+
* the matching format rules: `ship-` keys and `deploy-` deploy tokens are
|
|
644
|
+
* validated strictly; opaque tokens (OAuth access tokens, future populations)
|
|
645
|
+
* only need to be non-empty — their validity is the server's to decide.
|
|
646
|
+
*/
|
|
647
|
+
export declare function validateToken(token: string): void;
|
|
648
|
+
/**
|
|
649
|
+
* Validate a caller identifier against the `CALLER` shape. The server
|
|
650
|
+
* silently ignores malformed values (the header is unauthenticated); clients
|
|
651
|
+
* call this at configuration time so the drop never silently happens.
|
|
652
|
+
*/
|
|
653
|
+
export declare function validateCaller(caller: string): void;
|
|
578
654
|
/**
|
|
579
655
|
* Validate API URL format
|
|
580
656
|
*/
|
|
@@ -636,24 +712,6 @@ export interface StaticFile {
|
|
|
636
712
|
/** The size of the file in bytes. */
|
|
637
713
|
size: number;
|
|
638
714
|
}
|
|
639
|
-
/**
|
|
640
|
-
* Resolved client configuration with `apiUrl` defaulted.
|
|
641
|
-
*
|
|
642
|
-
* Produced by the SDK after layering its credential sources (constructor
|
|
643
|
-
* options on top of `SHIP_*` env vars in Node; constructor options only in
|
|
644
|
-
* Browser) and applying the `DEFAULT_API` fallback. File-based sources
|
|
645
|
-
* (`.shiprc`, `package.json` `"ship"` key) are the CLI's responsibility and
|
|
646
|
-
* are merged in *before* construction — by the time a `ResolvedConfig`
|
|
647
|
-
* exists, every source has already collapsed into the constructor argument.
|
|
648
|
-
*/
|
|
649
|
-
export interface ResolvedConfig {
|
|
650
|
-
/** API URL — always present after resolution, defaults to `DEFAULT_API`. */
|
|
651
|
-
apiUrl: string;
|
|
652
|
-
/** API key for authenticated deployments. */
|
|
653
|
-
apiKey?: string;
|
|
654
|
-
/** Deploy token used as the request credential (`token-{64-hex}`). */
|
|
655
|
-
deployToken?: string;
|
|
656
|
-
}
|
|
657
715
|
/**
|
|
658
716
|
* Progress information for deploy/upload operations.
|
|
659
717
|
* Provides consistent percentage-based progress with byte-level details.
|
|
@@ -707,6 +765,8 @@ export interface DeploymentUploadOptions {
|
|
|
707
765
|
prerender?: boolean;
|
|
708
766
|
/** @internal Trigger server-side SPA detection. Only available via /upload endpoint. */
|
|
709
767
|
spa?: boolean;
|
|
768
|
+
/** @internal reCAPTCHA proof for the anonymous human deploy channel. Only available via /upload endpoint. */
|
|
769
|
+
captcha?: string;
|
|
710
770
|
}
|
|
711
771
|
/**
|
|
712
772
|
* Deployment resource interface - the contract all implementations must follow
|
|
@@ -746,7 +806,7 @@ export interface DomainResource {
|
|
|
746
806
|
* Account resource interface - the contract all implementations must follow
|
|
747
807
|
*/
|
|
748
808
|
export interface AccountResource {
|
|
749
|
-
get: () => Promise<
|
|
809
|
+
get: () => Promise<AccountGetResponse>;
|
|
750
810
|
}
|
|
751
811
|
/**
|
|
752
812
|
* Token resource interface - the contract all implementations must follow
|
package/dist/index.js
CHANGED
|
@@ -417,6 +417,31 @@ export function hasUnbuiltMarker(filePath) {
|
|
|
417
417
|
const segments = filePath.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
418
418
|
return segments.some(s => UNBUILT_PROJECT_MARKERS.has(s));
|
|
419
419
|
}
|
|
420
|
+
// =============================================================================
|
|
421
|
+
// CREDENTIAL SHAPES
|
|
422
|
+
// =============================================================================
|
|
423
|
+
// The one address for credential vocabulary: how a request is authorized
|
|
424
|
+
// (AuthMethod), the shapes that distinguish populations on the wire
|
|
425
|
+
// (API_KEY, DEPLOY_TOKEN, CALLER), the single dispatch over them (TokenKind,
|
|
426
|
+
// classifyToken), and the delegated-access scopes (OAuthScope).
|
|
427
|
+
/**
|
|
428
|
+
* How a request (or recorded activity) was authorized.
|
|
429
|
+
*
|
|
430
|
+
* Client populations: `SESSION` (first-party cookie), `API_KEY` (`ship-`
|
|
431
|
+
* key), `TOKEN` (`deploy-` deploy token), `AGENT` (anonymous public deploy —
|
|
432
|
+
* no credential; the platform grants the public-account identity per
|
|
433
|
+
* request), `OAUTH` (delegated access token). Server populations: `WEBHOOK`
|
|
434
|
+
* (signed webhook processing), `SYSTEM` (scheduled/background jobs).
|
|
435
|
+
*/
|
|
436
|
+
export const AuthMethod = {
|
|
437
|
+
SESSION: 'session',
|
|
438
|
+
API_KEY: 'apiKey',
|
|
439
|
+
TOKEN: 'token',
|
|
440
|
+
AGENT: 'agent',
|
|
441
|
+
OAUTH: 'oauth',
|
|
442
|
+
WEBHOOK: 'webhook',
|
|
443
|
+
SYSTEM: 'system'
|
|
444
|
+
};
|
|
420
445
|
/**
|
|
421
446
|
* Shape constants for API keys (`ship-{64 hex chars}`).
|
|
422
447
|
* Single source of truth used by validation utilities and auth middleware.
|
|
@@ -432,26 +457,83 @@ export const API_KEY = {
|
|
|
432
457
|
HINT_LENGTH: 4,
|
|
433
458
|
};
|
|
434
459
|
/**
|
|
435
|
-
* Shape constants for deploy tokens (`
|
|
460
|
+
* Shape constants for deploy tokens (`deploy-{64 hex chars}`).
|
|
436
461
|
* Single source of truth used by validation utilities and auth middleware.
|
|
437
462
|
*/
|
|
438
463
|
export const DEPLOY_TOKEN = {
|
|
439
464
|
/** Prefix that identifies a deploy token. */
|
|
440
|
-
PREFIX: '
|
|
465
|
+
PREFIX: 'deploy-',
|
|
441
466
|
/** Number of hex characters following the prefix. */
|
|
442
467
|
HEX_LENGTH: 64,
|
|
443
|
-
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH =
|
|
444
|
-
TOTAL_LENGTH:
|
|
468
|
+
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 71`). */
|
|
469
|
+
TOTAL_LENGTH: 71,
|
|
445
470
|
};
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
471
|
+
/**
|
|
472
|
+
* Shape constants for caller identifiers (the `X-Caller` instance-identity
|
|
473
|
+
* header — rate-limit bucketing for multi-tenant orchestrators). The API
|
|
474
|
+
* normalizes case and silently ignores malformed values (the header is
|
|
475
|
+
* unauthenticated); clients validate at the boundary via `validateCaller`,
|
|
476
|
+
* so a value the server would drop fails fast instead.
|
|
477
|
+
*/
|
|
478
|
+
export const CALLER = {
|
|
479
|
+
/** HTTP header name. */
|
|
480
|
+
HEADER: 'X-Caller',
|
|
481
|
+
/** Maximum identifier length. */
|
|
482
|
+
MAX_LENGTH: 128,
|
|
483
|
+
/** Allowed characters: alphanumeric, dot, underscore, hyphen. */
|
|
484
|
+
PATTERN: /^[a-zA-Z0-9._-]+$/,
|
|
485
|
+
};
|
|
486
|
+
/**
|
|
487
|
+
* Token populations distinguishable by shape. The platform carries every
|
|
488
|
+
* client token in one wire slot (`Authorization: Bearer <value>`) and
|
|
489
|
+
* classifies by value, never by a side channel — this is the classifier.
|
|
490
|
+
*
|
|
491
|
+
* `API_KEY` and `DEPLOY_TOKEN` *are* `AuthMethod.API_KEY` and
|
|
492
|
+
* `AuthMethod.TOKEN` — the equality is structural, so a classification flows
|
|
493
|
+
* straight into an auth method and the pair can never drift. `OPAQUE` is any
|
|
494
|
+
* other value — shape says nothing about it, so only a lookup can. Today the
|
|
495
|
+
* server refuses every opaque bearer; the OAuth access-token population
|
|
496
|
+
* resolves there when the authorization server ships.
|
|
497
|
+
*/
|
|
498
|
+
export const TokenKind = {
|
|
499
|
+
API_KEY: AuthMethod.API_KEY,
|
|
500
|
+
DEPLOY_TOKEN: AuthMethod.TOKEN,
|
|
501
|
+
OPAQUE: 'opaque',
|
|
453
502
|
};
|
|
454
|
-
|
|
503
|
+
/**
|
|
504
|
+
* Classify a client token by shape. The single dispatch used by both sides
|
|
505
|
+
* of the wire: API auth middleware (which population is this credential?)
|
|
506
|
+
* and SDK validation (which format rules apply before sending?). Sharing it
|
|
507
|
+
* is what guarantees client and server can never disagree on dispatch.
|
|
508
|
+
*/
|
|
509
|
+
export function classifyToken(token) {
|
|
510
|
+
if (token.startsWith(API_KEY.PREFIX))
|
|
511
|
+
return TokenKind.API_KEY;
|
|
512
|
+
if (token.startsWith(DEPLOY_TOKEN.PREFIX))
|
|
513
|
+
return TokenKind.DEPLOY_TOKEN;
|
|
514
|
+
return TokenKind.OPAQUE;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* OAuth scope vocabulary for delegated third-party access tokens.
|
|
518
|
+
* Single source of truth used by the authorization server (advertised in
|
|
519
|
+
* `scopes_supported`), the API's scope-enforcement middleware, and consent UI
|
|
520
|
+
* copy. The standard `offline_access` scope (refresh tokens) is not platform
|
|
521
|
+
* vocabulary and is deliberately absent — the middleware never checks it.
|
|
522
|
+
*
|
|
523
|
+
* Deliberately absent by design: any `tokens:*` scope, `account:write`, or
|
|
524
|
+
* admin scope — a delegated app must never mint credentials, delete the
|
|
525
|
+
* account, or act as admin.
|
|
526
|
+
*/
|
|
527
|
+
export const OAuthScope = {
|
|
528
|
+
ACCOUNT_READ: 'account:read',
|
|
529
|
+
DEPLOYMENTS_READ: 'deployments:read',
|
|
530
|
+
DEPLOYMENTS_WRITE: 'deployments:write',
|
|
531
|
+
DOMAINS_READ: 'domains:read',
|
|
532
|
+
DOMAINS_WRITE: 'domains:write',
|
|
533
|
+
};
|
|
534
|
+
// =============================================================================
|
|
535
|
+
// DEPLOYMENT CONFIGURATION CONSTANTS
|
|
536
|
+
// =============================================================================
|
|
455
537
|
export const DEPLOYMENT_CONFIG_FILENAME = 'ship.json';
|
|
456
538
|
/** Default ship.json config for SPA routing. Single source of truth — used by both API and SDK. */
|
|
457
539
|
export const SPA_DEFAULT_CONFIG = { rewrites: [{ source: '/(.*)', destination: '/index.html' }] };
|
|
@@ -459,33 +541,59 @@ export const SPA_DEFAULT_CONFIG = { rewrites: [{ source: '/(.*)', destination: '
|
|
|
459
541
|
// VALIDATION UTILITIES
|
|
460
542
|
// =============================================================================
|
|
461
543
|
/**
|
|
462
|
-
*
|
|
544
|
+
* Shared rule for prefixed credentials: `{PREFIX}{HEX_LENGTH hex chars}`.
|
|
545
|
+
* The regex derives from the shape constants, so the validators can never
|
|
546
|
+
* drift from the shapes `classifyToken` dispatches on.
|
|
463
547
|
*/
|
|
464
|
-
|
|
465
|
-
if (!
|
|
466
|
-
throw ShipError.validation(
|
|
548
|
+
function validatePrefixedCredential(value, shape, label) {
|
|
549
|
+
if (!value.startsWith(shape.PREFIX)) {
|
|
550
|
+
throw ShipError.validation(`${label} must start with "${shape.PREFIX}"`);
|
|
467
551
|
}
|
|
468
|
-
if (
|
|
469
|
-
throw ShipError.validation(
|
|
552
|
+
if (value.length !== shape.TOTAL_LENGTH) {
|
|
553
|
+
throw ShipError.validation(`${label} must be ${shape.TOTAL_LENGTH} characters total (${shape.PREFIX} + ${shape.HEX_LENGTH} hex chars)`);
|
|
470
554
|
}
|
|
471
|
-
const hexPart =
|
|
472
|
-
if (
|
|
473
|
-
throw ShipError.validation(
|
|
555
|
+
const hexPart = value.slice(shape.PREFIX.length);
|
|
556
|
+
if (!new RegExp(`^[a-f0-9]{${shape.HEX_LENGTH}}$`, 'i').test(hexPart)) {
|
|
557
|
+
throw ShipError.validation(`${label} must contain ${shape.HEX_LENGTH} hexadecimal characters after "${shape.PREFIX}" prefix`);
|
|
474
558
|
}
|
|
475
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* Validate API key format
|
|
562
|
+
*/
|
|
563
|
+
export function validateApiKey(apiKey) {
|
|
564
|
+
validatePrefixedCredential(apiKey, API_KEY, 'API key');
|
|
565
|
+
}
|
|
476
566
|
/**
|
|
477
567
|
* Validate deploy token format
|
|
478
568
|
*/
|
|
479
569
|
export function validateDeployToken(deployToken) {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
570
|
+
validatePrefixedCredential(deployToken, DEPLOY_TOKEN, 'Deploy token');
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Validate a client token of any population. Classifies by shape and applies
|
|
574
|
+
* the matching format rules: `ship-` keys and `deploy-` deploy tokens are
|
|
575
|
+
* validated strictly; opaque tokens (OAuth access tokens, future populations)
|
|
576
|
+
* only need to be non-empty — their validity is the server's to decide.
|
|
577
|
+
*/
|
|
578
|
+
export function validateToken(token) {
|
|
579
|
+
switch (classifyToken(token)) {
|
|
580
|
+
case TokenKind.API_KEY:
|
|
581
|
+
return validateApiKey(token);
|
|
582
|
+
case TokenKind.DEPLOY_TOKEN:
|
|
583
|
+
return validateDeployToken(token);
|
|
584
|
+
case TokenKind.OPAQUE:
|
|
585
|
+
if (!token)
|
|
586
|
+
throw ShipError.validation('Token must be a non-empty string');
|
|
485
587
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Validate a caller identifier against the `CALLER` shape. The server
|
|
591
|
+
* silently ignores malformed values (the header is unauthenticated); clients
|
|
592
|
+
* call this at configuration time so the drop never silently happens.
|
|
593
|
+
*/
|
|
594
|
+
export function validateCaller(caller) {
|
|
595
|
+
if (!caller || caller.length > CALLER.MAX_LENGTH || !CALLER.PATTERN.test(caller)) {
|
|
596
|
+
throw ShipError.validation(`Caller must be 1-${CALLER.MAX_LENGTH} characters: letters, digits, dots, underscores, or hyphens`);
|
|
489
597
|
}
|
|
490
598
|
}
|
|
491
599
|
/**
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -206,31 +206,10 @@ export interface DomainValidateResponse {
|
|
|
206
206
|
// TOKEN TYPES
|
|
207
207
|
// =============================================================================
|
|
208
208
|
|
|
209
|
-
/**
|
|
210
|
-
* Deployment token for automated deployments
|
|
211
|
-
*/
|
|
212
|
-
export interface Token {
|
|
213
|
-
/** 7-char management identifier */
|
|
214
|
-
readonly token: string;
|
|
215
|
-
/** The account this token belongs to */
|
|
216
|
-
readonly account: string;
|
|
217
|
-
/** SHA256 hash of the raw credential (auth lookups only, never exposed to users) */
|
|
218
|
-
readonly hash: string;
|
|
219
|
-
/** IP-lock. Non-null = single-use (claimable only from this IP, once); null = multi-use. */
|
|
220
|
-
readonly ip: string | null;
|
|
221
|
-
/** Labels for categorization and filtering (lowercase, alphanumeric with separators). Always present, empty array when none. */
|
|
222
|
-
labels: string[];
|
|
223
|
-
/** Unix timestamp (seconds) when token was created */
|
|
224
|
-
readonly created: number;
|
|
225
|
-
/** Unix timestamp (seconds) when token expires, null for never */
|
|
226
|
-
readonly expires: number | null;
|
|
227
|
-
/** Consumption timestamp. Single-use: gates re-use (set once). Multi-use: refreshed on every claim. Null = never claimed. */
|
|
228
|
-
readonly used: number | null;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
209
|
/**
|
|
232
210
|
* Token as returned by the list endpoint.
|
|
233
|
-
*
|
|
211
|
+
* The secret is shown once at creation and never again — listings carry
|
|
212
|
+
* only the management identifier and lifecycle metadata.
|
|
234
213
|
*/
|
|
235
214
|
export interface TokenListItem {
|
|
236
215
|
/** 7-char management identifier (e.g., "a1b2c3d") */
|
|
@@ -241,7 +220,7 @@ export interface TokenListItem {
|
|
|
241
220
|
readonly created: number;
|
|
242
221
|
/** Unix timestamp (seconds) when token expires, null for never */
|
|
243
222
|
readonly expires: number | null;
|
|
244
|
-
/**
|
|
223
|
+
/** Unix timestamp (seconds) of the last request authenticated with this token, null if never used */
|
|
245
224
|
readonly used: number | null;
|
|
246
225
|
}
|
|
247
226
|
|
|
@@ -321,6 +300,21 @@ export interface Account {
|
|
|
321
300
|
readonly grace: number | null;
|
|
322
301
|
}
|
|
323
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Account as returned by `GET /account` — the entity plus how the request
|
|
305
|
+
* was authorized, so `whoami` can answer "what credential am I holding?".
|
|
306
|
+
* Request-scoped fields live on the response type, never on the entity
|
|
307
|
+
* (the `DeploymentCreateResponse` pattern).
|
|
308
|
+
*/
|
|
309
|
+
export interface AccountGetResponse extends Account {
|
|
310
|
+
/** How the request that produced this response was authorized. */
|
|
311
|
+
readonly authMethod: AuthMethodType;
|
|
312
|
+
/** Present (and true) only when the caller is an operator acting as themselves. */
|
|
313
|
+
readonly isAdmin?: true;
|
|
314
|
+
/** Present only during read-only admin impersonation: the operator's account id. */
|
|
315
|
+
readonly impersonatedBy?: string;
|
|
316
|
+
}
|
|
317
|
+
|
|
324
318
|
/**
|
|
325
319
|
* Account-specific configuration overrides
|
|
326
320
|
* Allows per-account customization of limits without changing plan
|
|
@@ -666,15 +660,14 @@ export function isShipError(error: unknown): error is ShipError {
|
|
|
666
660
|
// =============================================================================
|
|
667
661
|
|
|
668
662
|
/**
|
|
669
|
-
* Plan-based platform limits returned by the `/
|
|
663
|
+
* Plan-based platform limits returned by the `/limits` endpoint.
|
|
670
664
|
*
|
|
671
665
|
* The SDK fetches these once on first API call to drive client-side
|
|
672
666
|
* file-size / file-count / total-size validation that mirrors what the API
|
|
673
667
|
* would enforce server-side. Limits vary by account plan.
|
|
674
668
|
*
|
|
675
|
-
*
|
|
676
|
-
*
|
|
677
|
-
* caps for the current account.
|
|
669
|
+
* These are the *platform's* posted caps for the current account — server
|
|
670
|
+
* truth delivered at runtime, never hard-coded on the client.
|
|
678
671
|
*/
|
|
679
672
|
export interface PlatformLimits {
|
|
680
673
|
/** Maximum size in bytes for a single file. */
|
|
@@ -807,6 +800,35 @@ export interface PingResponse {
|
|
|
807
800
|
timestamp?: number;
|
|
808
801
|
}
|
|
809
802
|
|
|
803
|
+
// =============================================================================
|
|
804
|
+
// CREDENTIAL SHAPES
|
|
805
|
+
// =============================================================================
|
|
806
|
+
// The one address for credential vocabulary: how a request is authorized
|
|
807
|
+
// (AuthMethod), the shapes that distinguish populations on the wire
|
|
808
|
+
// (API_KEY, DEPLOY_TOKEN, CALLER), the single dispatch over them (TokenKind,
|
|
809
|
+
// classifyToken), and the delegated-access scopes (OAuthScope).
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* How a request (or recorded activity) was authorized.
|
|
813
|
+
*
|
|
814
|
+
* Client populations: `SESSION` (first-party cookie), `API_KEY` (`ship-`
|
|
815
|
+
* key), `TOKEN` (`deploy-` deploy token), `AGENT` (anonymous public deploy —
|
|
816
|
+
* no credential; the platform grants the public-account identity per
|
|
817
|
+
* request), `OAUTH` (delegated access token). Server populations: `WEBHOOK`
|
|
818
|
+
* (signed webhook processing), `SYSTEM` (scheduled/background jobs).
|
|
819
|
+
*/
|
|
820
|
+
export const AuthMethod = {
|
|
821
|
+
SESSION: 'session',
|
|
822
|
+
API_KEY: 'apiKey',
|
|
823
|
+
TOKEN: 'token',
|
|
824
|
+
AGENT: 'agent',
|
|
825
|
+
OAUTH: 'oauth',
|
|
826
|
+
WEBHOOK: 'webhook',
|
|
827
|
+
SYSTEM: 'system'
|
|
828
|
+
} as const;
|
|
829
|
+
|
|
830
|
+
export type AuthMethodType = typeof AuthMethod[keyof typeof AuthMethod];
|
|
831
|
+
|
|
810
832
|
/**
|
|
811
833
|
* Shape constants for API keys (`ship-{64 hex chars}`).
|
|
812
834
|
* Single source of truth used by validation utilities and auth middleware.
|
|
@@ -823,30 +845,91 @@ export const API_KEY = {
|
|
|
823
845
|
} as const;
|
|
824
846
|
|
|
825
847
|
/**
|
|
826
|
-
* Shape constants for deploy tokens (`
|
|
848
|
+
* Shape constants for deploy tokens (`deploy-{64 hex chars}`).
|
|
827
849
|
* Single source of truth used by validation utilities and auth middleware.
|
|
828
850
|
*/
|
|
829
851
|
export const DEPLOY_TOKEN = {
|
|
830
852
|
/** Prefix that identifies a deploy token. */
|
|
831
|
-
PREFIX: '
|
|
853
|
+
PREFIX: 'deploy-',
|
|
832
854
|
/** Number of hex characters following the prefix. */
|
|
833
855
|
HEX_LENGTH: 64,
|
|
834
|
-
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH =
|
|
835
|
-
TOTAL_LENGTH:
|
|
856
|
+
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 71`). */
|
|
857
|
+
TOTAL_LENGTH: 71,
|
|
836
858
|
} as const;
|
|
837
859
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
860
|
+
/**
|
|
861
|
+
* Shape constants for caller identifiers (the `X-Caller` instance-identity
|
|
862
|
+
* header — rate-limit bucketing for multi-tenant orchestrators). The API
|
|
863
|
+
* normalizes case and silently ignores malformed values (the header is
|
|
864
|
+
* unauthenticated); clients validate at the boundary via `validateCaller`,
|
|
865
|
+
* so a value the server would drop fails fast instead.
|
|
866
|
+
*/
|
|
867
|
+
export const CALLER = {
|
|
868
|
+
/** HTTP header name. */
|
|
869
|
+
HEADER: 'X-Caller',
|
|
870
|
+
/** Maximum identifier length. */
|
|
871
|
+
MAX_LENGTH: 128,
|
|
872
|
+
/** Allowed characters: alphanumeric, dot, underscore, hyphen. */
|
|
873
|
+
PATTERN: /^[a-zA-Z0-9._-]+$/,
|
|
845
874
|
} as const;
|
|
846
875
|
|
|
847
|
-
|
|
876
|
+
/**
|
|
877
|
+
* Token populations distinguishable by shape. The platform carries every
|
|
878
|
+
* client token in one wire slot (`Authorization: Bearer <value>`) and
|
|
879
|
+
* classifies by value, never by a side channel — this is the classifier.
|
|
880
|
+
*
|
|
881
|
+
* `API_KEY` and `DEPLOY_TOKEN` *are* `AuthMethod.API_KEY` and
|
|
882
|
+
* `AuthMethod.TOKEN` — the equality is structural, so a classification flows
|
|
883
|
+
* straight into an auth method and the pair can never drift. `OPAQUE` is any
|
|
884
|
+
* other value — shape says nothing about it, so only a lookup can. Today the
|
|
885
|
+
* server refuses every opaque bearer; the OAuth access-token population
|
|
886
|
+
* resolves there when the authorization server ships.
|
|
887
|
+
*/
|
|
888
|
+
export const TokenKind = {
|
|
889
|
+
API_KEY: AuthMethod.API_KEY,
|
|
890
|
+
DEPLOY_TOKEN: AuthMethod.TOKEN,
|
|
891
|
+
OPAQUE: 'opaque',
|
|
892
|
+
} as const;
|
|
893
|
+
|
|
894
|
+
export type TokenKindType = typeof TokenKind[keyof typeof TokenKind];
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Classify a client token by shape. The single dispatch used by both sides
|
|
898
|
+
* of the wire: API auth middleware (which population is this credential?)
|
|
899
|
+
* and SDK validation (which format rules apply before sending?). Sharing it
|
|
900
|
+
* is what guarantees client and server can never disagree on dispatch.
|
|
901
|
+
*/
|
|
902
|
+
export function classifyToken(token: string): TokenKindType {
|
|
903
|
+
if (token.startsWith(API_KEY.PREFIX)) return TokenKind.API_KEY;
|
|
904
|
+
if (token.startsWith(DEPLOY_TOKEN.PREFIX)) return TokenKind.DEPLOY_TOKEN;
|
|
905
|
+
return TokenKind.OPAQUE;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* OAuth scope vocabulary for delegated third-party access tokens.
|
|
910
|
+
* Single source of truth used by the authorization server (advertised in
|
|
911
|
+
* `scopes_supported`), the API's scope-enforcement middleware, and consent UI
|
|
912
|
+
* copy. The standard `offline_access` scope (refresh tokens) is not platform
|
|
913
|
+
* vocabulary and is deliberately absent — the middleware never checks it.
|
|
914
|
+
*
|
|
915
|
+
* Deliberately absent by design: any `tokens:*` scope, `account:write`, or
|
|
916
|
+
* admin scope — a delegated app must never mint credentials, delete the
|
|
917
|
+
* account, or act as admin.
|
|
918
|
+
*/
|
|
919
|
+
export const OAuthScope = {
|
|
920
|
+
ACCOUNT_READ: 'account:read',
|
|
921
|
+
DEPLOYMENTS_READ: 'deployments:read',
|
|
922
|
+
DEPLOYMENTS_WRITE: 'deployments:write',
|
|
923
|
+
DOMAINS_READ: 'domains:read',
|
|
924
|
+
DOMAINS_WRITE: 'domains:write',
|
|
925
|
+
} as const;
|
|
926
|
+
|
|
927
|
+
export type OAuthScopeType = typeof OAuthScope[keyof typeof OAuthScope];
|
|
928
|
+
|
|
929
|
+
// =============================================================================
|
|
930
|
+
// DEPLOYMENT CONFIGURATION CONSTANTS
|
|
931
|
+
// =============================================================================
|
|
848
932
|
|
|
849
|
-
// Deployment Configuration
|
|
850
933
|
export const DEPLOYMENT_CONFIG_FILENAME = 'ship.json';
|
|
851
934
|
|
|
852
935
|
/** Default ship.json config for SPA routing. Single source of truth — used by both API and SDK. */
|
|
@@ -857,38 +940,70 @@ export const SPA_DEFAULT_CONFIG = { rewrites: [{ source: '/(.*)', destination: '
|
|
|
857
940
|
// =============================================================================
|
|
858
941
|
|
|
859
942
|
/**
|
|
860
|
-
*
|
|
943
|
+
* Shared rule for prefixed credentials: `{PREFIX}{HEX_LENGTH hex chars}`.
|
|
944
|
+
* The regex derives from the shape constants, so the validators can never
|
|
945
|
+
* drift from the shapes `classifyToken` dispatches on.
|
|
861
946
|
*/
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
947
|
+
function validatePrefixedCredential(
|
|
948
|
+
value: string,
|
|
949
|
+
shape: { PREFIX: string; HEX_LENGTH: number; TOTAL_LENGTH: number },
|
|
950
|
+
label: string
|
|
951
|
+
): void {
|
|
952
|
+
if (!value.startsWith(shape.PREFIX)) {
|
|
953
|
+
throw ShipError.validation(`${label} must start with "${shape.PREFIX}"`);
|
|
865
954
|
}
|
|
866
955
|
|
|
867
|
-
if (
|
|
868
|
-
throw ShipError.validation(
|
|
956
|
+
if (value.length !== shape.TOTAL_LENGTH) {
|
|
957
|
+
throw ShipError.validation(`${label} must be ${shape.TOTAL_LENGTH} characters total (${shape.PREFIX} + ${shape.HEX_LENGTH} hex chars)`);
|
|
869
958
|
}
|
|
870
959
|
|
|
871
|
-
const hexPart =
|
|
872
|
-
if (
|
|
873
|
-
throw ShipError.validation(
|
|
960
|
+
const hexPart = value.slice(shape.PREFIX.length);
|
|
961
|
+
if (!new RegExp(`^[a-f0-9]{${shape.HEX_LENGTH}}$`, 'i').test(hexPart)) {
|
|
962
|
+
throw ShipError.validation(`${label} must contain ${shape.HEX_LENGTH} hexadecimal characters after "${shape.PREFIX}" prefix`);
|
|
874
963
|
}
|
|
875
964
|
}
|
|
876
965
|
|
|
966
|
+
/**
|
|
967
|
+
* Validate API key format
|
|
968
|
+
*/
|
|
969
|
+
export function validateApiKey(apiKey: string): void {
|
|
970
|
+
validatePrefixedCredential(apiKey, API_KEY, 'API key');
|
|
971
|
+
}
|
|
972
|
+
|
|
877
973
|
/**
|
|
878
974
|
* Validate deploy token format
|
|
879
975
|
*/
|
|
880
976
|
export function validateDeployToken(deployToken: string): void {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
}
|
|
977
|
+
validatePrefixedCredential(deployToken, DEPLOY_TOKEN, 'Deploy token');
|
|
978
|
+
}
|
|
884
979
|
|
|
885
|
-
|
|
886
|
-
|
|
980
|
+
/**
|
|
981
|
+
* Validate a client token of any population. Classifies by shape and applies
|
|
982
|
+
* the matching format rules: `ship-` keys and `deploy-` deploy tokens are
|
|
983
|
+
* validated strictly; opaque tokens (OAuth access tokens, future populations)
|
|
984
|
+
* only need to be non-empty — their validity is the server's to decide.
|
|
985
|
+
*/
|
|
986
|
+
export function validateToken(token: string): void {
|
|
987
|
+
switch (classifyToken(token)) {
|
|
988
|
+
case TokenKind.API_KEY:
|
|
989
|
+
return validateApiKey(token);
|
|
990
|
+
case TokenKind.DEPLOY_TOKEN:
|
|
991
|
+
return validateDeployToken(token);
|
|
992
|
+
case TokenKind.OPAQUE:
|
|
993
|
+
if (!token) throw ShipError.validation('Token must be a non-empty string');
|
|
887
994
|
}
|
|
995
|
+
}
|
|
888
996
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
997
|
+
/**
|
|
998
|
+
* Validate a caller identifier against the `CALLER` shape. The server
|
|
999
|
+
* silently ignores malformed values (the header is unauthenticated); clients
|
|
1000
|
+
* call this at configuration time so the drop never silently happens.
|
|
1001
|
+
*/
|
|
1002
|
+
export function validateCaller(caller: string): void {
|
|
1003
|
+
if (!caller || caller.length > CALLER.MAX_LENGTH || !CALLER.PATTERN.test(caller)) {
|
|
1004
|
+
throw ShipError.validation(
|
|
1005
|
+
`Caller must be 1-${CALLER.MAX_LENGTH} characters: letters, digits, dots, underscores, or hyphens`
|
|
1006
|
+
);
|
|
892
1007
|
}
|
|
893
1008
|
}
|
|
894
1009
|
|
|
@@ -989,29 +1104,6 @@ export interface StaticFile {
|
|
|
989
1104
|
size: number;
|
|
990
1105
|
}
|
|
991
1106
|
|
|
992
|
-
// =============================================================================
|
|
993
|
-
// PLATFORM CONFIGURATION
|
|
994
|
-
// =============================================================================
|
|
995
|
-
|
|
996
|
-
/**
|
|
997
|
-
* Resolved client configuration with `apiUrl` defaulted.
|
|
998
|
-
*
|
|
999
|
-
* Produced by the SDK after layering its credential sources (constructor
|
|
1000
|
-
* options on top of `SHIP_*` env vars in Node; constructor options only in
|
|
1001
|
-
* Browser) and applying the `DEFAULT_API` fallback. File-based sources
|
|
1002
|
-
* (`.shiprc`, `package.json` `"ship"` key) are the CLI's responsibility and
|
|
1003
|
-
* are merged in *before* construction — by the time a `ResolvedConfig`
|
|
1004
|
-
* exists, every source has already collapsed into the constructor argument.
|
|
1005
|
-
*/
|
|
1006
|
-
export interface ResolvedConfig {
|
|
1007
|
-
/** API URL — always present after resolution, defaults to `DEFAULT_API`. */
|
|
1008
|
-
apiUrl: string;
|
|
1009
|
-
/** API key for authenticated deployments. */
|
|
1010
|
-
apiKey?: string;
|
|
1011
|
-
/** Deploy token used as the request credential (`token-{64-hex}`). */
|
|
1012
|
-
deployToken?: string;
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
1107
|
// =============================================================================
|
|
1016
1108
|
// PROGRESS TRACKING
|
|
1017
1109
|
// =============================================================================
|
|
@@ -1080,6 +1172,8 @@ export interface DeploymentUploadOptions {
|
|
|
1080
1172
|
prerender?: boolean;
|
|
1081
1173
|
/** @internal Trigger server-side SPA detection. Only available via /upload endpoint. */
|
|
1082
1174
|
spa?: boolean;
|
|
1175
|
+
/** @internal reCAPTCHA proof for the anonymous human deploy channel. Only available via /upload endpoint. */
|
|
1176
|
+
captcha?: string;
|
|
1083
1177
|
}
|
|
1084
1178
|
|
|
1085
1179
|
/**
|
|
@@ -1112,7 +1206,7 @@ export interface DomainResource {
|
|
|
1112
1206
|
* Account resource interface - the contract all implementations must follow
|
|
1113
1207
|
*/
|
|
1114
1208
|
export interface AccountResource {
|
|
1115
|
-
get: () => Promise<
|
|
1209
|
+
get: () => Promise<AccountGetResponse>;
|
|
1116
1210
|
}
|
|
1117
1211
|
|
|
1118
1212
|
/**
|