@shipstatic/types 2.8.0-beta.1 → 2.8.0-beta.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/index.d.ts CHANGED
@@ -1198,6 +1198,43 @@ export type TokenKindType = (typeof TokenKind)[keyof typeof TokenKind];
1198
1198
  * is what guarantees client and server can never disagree on dispatch.
1199
1199
  */
1200
1200
  export declare function classifyToken(token: string): TokenKindType;
1201
+ /**
1202
+ * Read the credential out of an `Authorization` header value — the step
1203
+ * BEFORE `classifyToken`, and the other half of the one wire slot this
1204
+ * section owns.
1205
+ *
1206
+ * Returns the credential's own bytes, or `null` when the header carries a
1207
+ * foreign scheme or nothing after the scheme.
1208
+ *
1209
+ * **The scheme is folded; the credential is not.** RFC 7235 §2.1 makes the
1210
+ * auth-scheme case-insensitive, so `bearer`, `Bearer` and `BEARER` are the
1211
+ * same header. The value after it is opaque and is compared literally
1212
+ * everywhere it is used — `ship-`/`deploy-`/`oauth-` are lowercase hex, and
1213
+ * folding them would make a credential match values it is not.
1214
+ *
1215
+ * **This platform has paid for the rule twice, which is why it has an owner
1216
+ * rather than a convention.** A spec-conformant `bearer ship-…` client was
1217
+ * refused for as long as the API's scheme test was spelled case-sensitively;
1218
+ * and `@better-auth/oauth-provider` carries the same defect in four places
1219
+ * today (`startsWith("Bearer ")`), which is precisely why the platform folds
1220
+ * the scheme itself and hands the provider a bare token.
1221
+ *
1222
+ * **ABSENCE is deliberately not this function's business.** A missing header
1223
+ * and an unreadable one are different facts, and the callers that care split
1224
+ * on them: the API worker's middleware distinguishes `absent` (the only
1225
+ * anonymous path) from `unreadable` (a presented credential that is refused),
1226
+ * and collapsing the two here would take that distinction away from the layer
1227
+ * that needs it. Callers check for the header themselves and pass its value.
1228
+ *
1229
+ * **Why this lives in the constitution rather than in a worker's `shared/`.**
1230
+ * It is the same wire boundary `classifyToken` already owns — one reads the
1231
+ * slot, the other dispatches on what came out — and a rule with two holders
1232
+ * whose drift is silent earns exactly one owner regardless of what the
1233
+ * convoy costs. The estate's recorded refusal to own a `Bearer` CONSTANT
1234
+ * stands and is a different thing: that is RFC vocabulary, the same reason
1235
+ * this package owns no `"POST"`. A parser is not a spelling.
1236
+ */
1237
+ export declare function readBearerValue(header: string): string | null;
1201
1238
  /**
1202
1239
  * OAuth scope vocabulary for delegated third-party access tokens.
1203
1240
  * Single source of truth used by the authorization server (advertised in
package/dist/index.js CHANGED
@@ -1015,9 +1015,10 @@ export function hasUnbuiltMarker(filePath) {
1015
1015
  // =============================================================================
1016
1016
  // The one address for credential vocabulary: where human identity lives
1017
1017
  // (AUTH_BASE_PATH), how a request is authorized (AuthMethod), the shapes
1018
- // that distinguish populations on the wire (API_KEY, DEPLOY_TOKEN, CALLER),
1019
- // the single dispatch over them (TokenKind, classifyToken), and the
1020
- // delegated-access scopes (OAuthScope).
1018
+ // that distinguish populations on the wire (API_KEY, DEPLOY_TOKEN,
1019
+ // OAUTH_TOKEN, CALLER), the two halves of the one Bearer slot
1020
+ // (readBearerValue reads it, classifyToken/TokenKind dispatch on what came
1021
+ // out), and the delegated-access scopes (OAuthScope).
1021
1022
  //
1022
1023
  // THE SHAPE LAW, in three clauses, over the `Authorization: Bearer` slot's
1023
1024
  // three populations below. The deployment claim code is the API's own
@@ -1194,6 +1195,49 @@ export function classifyToken(token) {
1194
1195
  return TokenKind.OAUTH;
1195
1196
  return TokenKind.OPAQUE;
1196
1197
  }
1198
+ /** The auth-scheme, lowercased — the form the comparison is made in. */
1199
+ const BEARER_SCHEME = 'bearer ';
1200
+ /**
1201
+ * Read the credential out of an `Authorization` header value — the step
1202
+ * BEFORE `classifyToken`, and the other half of the one wire slot this
1203
+ * section owns.
1204
+ *
1205
+ * Returns the credential's own bytes, or `null` when the header carries a
1206
+ * foreign scheme or nothing after the scheme.
1207
+ *
1208
+ * **The scheme is folded; the credential is not.** RFC 7235 §2.1 makes the
1209
+ * auth-scheme case-insensitive, so `bearer`, `Bearer` and `BEARER` are the
1210
+ * same header. The value after it is opaque and is compared literally
1211
+ * everywhere it is used — `ship-`/`deploy-`/`oauth-` are lowercase hex, and
1212
+ * folding them would make a credential match values it is not.
1213
+ *
1214
+ * **This platform has paid for the rule twice, which is why it has an owner
1215
+ * rather than a convention.** A spec-conformant `bearer ship-…` client was
1216
+ * refused for as long as the API's scheme test was spelled case-sensitively;
1217
+ * and `@better-auth/oauth-provider` carries the same defect in four places
1218
+ * today (`startsWith("Bearer ")`), which is precisely why the platform folds
1219
+ * the scheme itself and hands the provider a bare token.
1220
+ *
1221
+ * **ABSENCE is deliberately not this function's business.** A missing header
1222
+ * and an unreadable one are different facts, and the callers that care split
1223
+ * on them: the API worker's middleware distinguishes `absent` (the only
1224
+ * anonymous path) from `unreadable` (a presented credential that is refused),
1225
+ * and collapsing the two here would take that distinction away from the layer
1226
+ * that needs it. Callers check for the header themselves and pass its value.
1227
+ *
1228
+ * **Why this lives in the constitution rather than in a worker's `shared/`.**
1229
+ * It is the same wire boundary `classifyToken` already owns — one reads the
1230
+ * slot, the other dispatches on what came out — and a rule with two holders
1231
+ * whose drift is silent earns exactly one owner regardless of what the
1232
+ * convoy costs. The estate's recorded refusal to own a `Bearer` CONSTANT
1233
+ * stands and is a different thing: that is RFC vocabulary, the same reason
1234
+ * this package owns no `"POST"`. A parser is not a spelling.
1235
+ */
1236
+ export function readBearerValue(header) {
1237
+ if (header.slice(0, BEARER_SCHEME.length).toLowerCase() !== BEARER_SCHEME)
1238
+ return null;
1239
+ return header.slice(BEARER_SCHEME.length) || null;
1240
+ }
1197
1241
  /**
1198
1242
  * OAuth scope vocabulary for delegated third-party access tokens.
1199
1243
  * Single source of truth used by the authorization server (advertised in
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipstatic/types",
3
- "version": "2.8.0-beta.1",
3
+ "version": "2.8.0-beta.2",
4
4
  "description": "Shared types for ShipStatic platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/index.ts CHANGED
@@ -1697,9 +1697,10 @@ export interface PingResponse {
1697
1697
  // =============================================================================
1698
1698
  // The one address for credential vocabulary: where human identity lives
1699
1699
  // (AUTH_BASE_PATH), how a request is authorized (AuthMethod), the shapes
1700
- // that distinguish populations on the wire (API_KEY, DEPLOY_TOKEN, CALLER),
1701
- // the single dispatch over them (TokenKind, classifyToken), and the
1702
- // delegated-access scopes (OAuthScope).
1700
+ // that distinguish populations on the wire (API_KEY, DEPLOY_TOKEN,
1701
+ // OAUTH_TOKEN, CALLER), the two halves of the one Bearer slot
1702
+ // (readBearerValue reads it, classifyToken/TokenKind dispatch on what came
1703
+ // out), and the delegated-access scopes (OAuthScope).
1703
1704
  //
1704
1705
  // THE SHAPE LAW, in three clauses, over the `Authorization: Bearer` slot's
1705
1706
  // three populations below. The deployment claim code is the API's own
@@ -1886,6 +1887,50 @@ export function classifyToken(token: string): TokenKindType {
1886
1887
  return TokenKind.OPAQUE;
1887
1888
  }
1888
1889
 
1890
+ /** The auth-scheme, lowercased — the form the comparison is made in. */
1891
+ const BEARER_SCHEME = 'bearer ';
1892
+
1893
+ /**
1894
+ * Read the credential out of an `Authorization` header value — the step
1895
+ * BEFORE `classifyToken`, and the other half of the one wire slot this
1896
+ * section owns.
1897
+ *
1898
+ * Returns the credential's own bytes, or `null` when the header carries a
1899
+ * foreign scheme or nothing after the scheme.
1900
+ *
1901
+ * **The scheme is folded; the credential is not.** RFC 7235 §2.1 makes the
1902
+ * auth-scheme case-insensitive, so `bearer`, `Bearer` and `BEARER` are the
1903
+ * same header. The value after it is opaque and is compared literally
1904
+ * everywhere it is used — `ship-`/`deploy-`/`oauth-` are lowercase hex, and
1905
+ * folding them would make a credential match values it is not.
1906
+ *
1907
+ * **This platform has paid for the rule twice, which is why it has an owner
1908
+ * rather than a convention.** A spec-conformant `bearer ship-…` client was
1909
+ * refused for as long as the API's scheme test was spelled case-sensitively;
1910
+ * and `@better-auth/oauth-provider` carries the same defect in four places
1911
+ * today (`startsWith("Bearer ")`), which is precisely why the platform folds
1912
+ * the scheme itself and hands the provider a bare token.
1913
+ *
1914
+ * **ABSENCE is deliberately not this function's business.** A missing header
1915
+ * and an unreadable one are different facts, and the callers that care split
1916
+ * on them: the API worker's middleware distinguishes `absent` (the only
1917
+ * anonymous path) from `unreadable` (a presented credential that is refused),
1918
+ * and collapsing the two here would take that distinction away from the layer
1919
+ * that needs it. Callers check for the header themselves and pass its value.
1920
+ *
1921
+ * **Why this lives in the constitution rather than in a worker's `shared/`.**
1922
+ * It is the same wire boundary `classifyToken` already owns — one reads the
1923
+ * slot, the other dispatches on what came out — and a rule with two holders
1924
+ * whose drift is silent earns exactly one owner regardless of what the
1925
+ * convoy costs. The estate's recorded refusal to own a `Bearer` CONSTANT
1926
+ * stands and is a different thing: that is RFC vocabulary, the same reason
1927
+ * this package owns no `"POST"`. A parser is not a spelling.
1928
+ */
1929
+ export function readBearerValue(header: string): string | null {
1930
+ if (header.slice(0, BEARER_SCHEME.length).toLowerCase() !== BEARER_SCHEME) return null;
1931
+ return header.slice(BEARER_SCHEME.length) || null;
1932
+ }
1933
+
1889
1934
  /**
1890
1935
  * OAuth scope vocabulary for delegated third-party access tokens.
1891
1936
  * Single source of truth used by the authorization server (advertised in