Some checks failed
release / build-release (push) Has been cancelled
- IChannel: creators -> sub-channels -> video posts (public listing API, search mapped) - IRequiresMediaInfoCallback -> signed proxy URLs; stream controller rewrites HLS so the AES-128 key is fetched server-side with the session cookie, segments stay on the CDN - delivery/info cached per token lifetime and throttled (~2/min) - config page: paste sails.sid + validate, extra creators, quality, search test - scripts/package.sh -> plugin folder + zip + md5 + manifest.json; Gitea release workflow - research docs, HAR analysis (HAR itself gitignored), install-pi5.sh Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
132 lines
4.5 KiB
JavaScript
132 lines
4.5 KiB
JavaScript
/**
|
|
* Phase 3.0 authenticated API response-shape canary — constants.
|
|
*
|
|
* OIDC clientId / realm / issuer are taken from frontend archive evidence
|
|
* (build 4.5.22-316-d74397b entry JS: baseUrl auth.floatplane.com, realm floatplane,
|
|
* clientId fp-tv-app) and public OIDC discovery. Do not invent alternate clients.
|
|
*/
|
|
|
|
export const TOOL_ID = 'fp-api-shape-canary';
|
|
export const TOOL_VERSION = '3.1.0';
|
|
export const SCHEMA_VERSION = 1;
|
|
|
|
/** Custom User-Agent for read-only probes (identify the watch project). */
|
|
export const USER_AGENT = 'FloatplaneAPI-Watch/3.1 (api-shape-canary; read-only)';
|
|
|
|
export const API_BASE_URL = 'https://www.floatplane.com';
|
|
|
|
/**
|
|
* Keycloak / OIDC — evidence-backed defaults.
|
|
* Discovery: https://auth.floatplane.com/realms/floatplane/.well-known/openid-configuration
|
|
*/
|
|
export const OIDC = Object.freeze({
|
|
issuer: 'https://auth.floatplane.com/realms/floatplane',
|
|
wellKnownUrl:
|
|
'https://auth.floatplane.com/realms/floatplane/.well-known/openid-configuration',
|
|
/** Frontend TV device-auth config: clientId:"fp-tv-app" */
|
|
clientId: 'fp-tv-app',
|
|
realm: 'floatplane',
|
|
baseUrl: 'https://auth.floatplane.com',
|
|
/**
|
|
* One-shot / interactive default. Scheduled canary prefers scheduleScope.
|
|
* offline_access is advertised in discovery scopes_supported (observed 2026-10-11).
|
|
*/
|
|
defaultScope: 'openid',
|
|
/**
|
|
* Prefer offline refresh for scheduled runs. Still not "indefinite" — see
|
|
* docs/phase-3-1-api-shape-schedule.md for measured refresh_expires_in.
|
|
*/
|
|
scheduleScope: 'openid offline_access',
|
|
grantTypeDeviceCode: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
grantTypeRefreshToken: 'refresh_token',
|
|
});
|
|
|
|
/** Separate lane from Phase 1/2 frontend observation branch. */
|
|
export const SHAPE_MONITOR_BRANCH = 'cursor/api-shape-observation';
|
|
export const SHAPE_DEFAULT_BRANCH = 'main';
|
|
export const SHAPE_PR_TITLE_PREFIX = 'API shape canary:';
|
|
|
|
/** Evidence notes committed beside captures for auditability. */
|
|
export const OIDC_EVIDENCE = Object.freeze({
|
|
clientIdSource:
|
|
'artifacts/frontend/4.5.22-316-d74397b/.../js/index-BZVDPgzb.js — o_={baseUrl:"https://auth.floatplane.com",realm:"floatplane",clientId:"fp-tv-app",usesExtendedSecurity:!0,...}',
|
|
deviceGrantSource:
|
|
'OIDC discovery grant_types_supported includes urn:ietf:params:oauth:grant-type:device_code; device_authorization_endpoint present (observed 2026-10-02)',
|
|
refreshGrantSource:
|
|
'OIDC discovery grant_types_supported includes refresh_token; scopes_supported includes offline_access (observed 2026-10-11). Frontend refreshAccessToken requires DPoP when USE_DPOP; setOAuthTokenFromResponse reads refresh_expires_in as finite wall clock.',
|
|
});
|
|
|
|
/**
|
|
* Fixed read-only allowlist (Phase 3.0). Order matters for id discovery.
|
|
* No writes. No /delivery/info. No Hydravion.
|
|
*/
|
|
export const ALLOWLIST = Object.freeze([
|
|
{
|
|
id: 'user-self',
|
|
method: 'GET',
|
|
path: '/api/v3/user/self',
|
|
role: 'token-sanity',
|
|
auth: 'bearer',
|
|
},
|
|
{
|
|
id: 'user-subscriptions',
|
|
method: 'GET',
|
|
path: '/api/v3/user/subscriptions',
|
|
role: 'pick-creator',
|
|
auth: 'bearer',
|
|
},
|
|
{
|
|
id: 'content-creator',
|
|
method: 'GET',
|
|
path: '/api/v3/content/creator',
|
|
role: 'list-shape + post-id',
|
|
auth: 'bearer',
|
|
/** Query built at runtime: id, limit=1 */
|
|
queryKeys: ['id', 'limit'],
|
|
},
|
|
{
|
|
id: 'content-post',
|
|
method: 'GET',
|
|
path: '/api/v3/content/post',
|
|
role: 'primary-canary',
|
|
auth: 'bearer',
|
|
queryKeys: ['id'],
|
|
},
|
|
{
|
|
id: 'content-video',
|
|
method: 'GET',
|
|
path: '/api/v3/content/video',
|
|
role: 'optional-attachment',
|
|
auth: 'bearer',
|
|
optional: true,
|
|
queryKeys: ['id'],
|
|
},
|
|
]);
|
|
|
|
/** Unauthenticated companion (list shape only; detail post remains 403). */
|
|
export const UNAUTH_LIST = Object.freeze({
|
|
id: 'content-creator-unauth',
|
|
method: 'GET',
|
|
path: '/api/v3/content/creator',
|
|
role: 'unauth-list-companion',
|
|
auth: 'none',
|
|
/** Creator id used in assessment unauth sample (Linus Tech Tips). */
|
|
defaultCreatorId: '59f94c0bdd241b70349eb72b',
|
|
});
|
|
|
|
export const EXIT = Object.freeze({
|
|
SUCCESS: 0,
|
|
FAILURE: 1,
|
|
/** Structural drift vs baseline */
|
|
DRIFT: 2,
|
|
/** Missing token / needs human device approval */
|
|
NEEDS_AUTH: 3,
|
|
});
|
|
|
|
export const DEFAULT_ARTIFACTS_ROOT = 'artifacts/api-shape';
|
|
export const DEFAULT_TOKEN_FILE = 'state/api-shape-token.local';
|
|
/** Combined access token + DPoP key material (gitignored). Prefer over bare token file. */
|
|
export const DEFAULT_AUTH_FILE = 'state/api-shape-auth.local.json';
|
|
export const BASELINES_DIR = 'baselines';
|
|
export const CAPTURES_DIR = 'captures';
|