You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Strava data callable must fully consume successful recent-activity and statistics replies through the merged bounded native JSON reader before projection or return. If activity admission fails after both fetch responses resolve, it must begin best-effort cancellation of the unread successful statistics body without waiting, logging, or changing the fixed activity result.
Current projectors accept selected bounded fields while ignoring unknown fields. An otherwise accepted JSON object can therefore carry an arbitrarily large ignored string, polyline, numeric spelling, or additive field. No finite raw-body ceiling is mathematically backward-compatible with every value the old projector would accept.
Strava's official reference says the current calls return SummaryActivity[] and ActivityStats; this source requests five activities. The official schemas publish no response-byte, Content-Length, applicable maxLength, or body-size guarantee. These are deliberately chosen MPRC application safety budgets, not provider guarantees:
Activities: 1,048,576 content-decoded bytes (1 MiB) for the requested five summaries, allowing substantial margin for polylines and additive fields.
Statistics: 65,536 content-decoded bytes (64 KiB) for the current documented numeric statistics shape.
A legitimate larger Strava reply will fail closed with the existing fixed unavailable result. Any cap change requires a separate reviewed change and redacted non-production evidence; source/tests here do not claim provider compatibility or live sizing.
Missing Content-Length is allowed. Canonical declared-over-limit length rejects early; false-low length cannot bypass actual-byte counting. Every chunk counts toward the shared 4,096 limit.
Exact-limit activity JSON may project and continue. Byte/chunk overflow, malformed stream/read record/chunk, invalid UTF-8, or malformed JSON keeps the fixed data unavailable result. The reader cancels its unfinished activity body best-effort.
A bounded but invalid activity schema keeps the fixed data internal result.
On activity HTTP-admission failure, body failure, or schema failure after both fetch responses exist, begin best-effort cancellation of the unread statistics body only when it is an exact native confirmed-success response with an unused genuine body. Pass no reason; observe rejection; do not await, inspect, log, clone, tee, read, or expose it. Cleanup throw/rejection/pending promise cannot replace the activity result.
Preserve activity HTTP non-success no-body-read behavior. Its own body is not newly consumed or canceled by this child.
Only after a frozen activity projection succeeds, inspect statistics HTTP success for result processing and body consumption. On an activity failure after both fetches fulfill, the cleanup-only path may use the captured exact-native success check solely to decide whether to cancel; it may not read, parse, or project the statistics body or change the activity result.
Preserve statistics HTTP non-success/invalid admission as optional: do not read or newly cancel that body; return the successful activities with yearToDate and allTime null.
A confirmed-success statistics response uses OAUTH-001A2K — Bound Strava OAuth token JSON responses before parsing #614's reader with the 64 KiB ceiling. Transport/decode/parse/body failure remains fixed data unavailable; bounded schema failure remains fixed data internal; valid bounded data preserves the existing frozen result.
Neither successful data path may invoke a response's json, text, arrayBuffer, or bytes method, clone, or tee. Plain test objects and overridden native mixins cannot bypass the boundary.
Connection/secret reads and a possible earlier refresh CAS keep their existing order. This child adds no write, delete, timestamp, log, retry, or provider request.
Exact scope
functions/strava.js
two named application ceilings;
reuse of readBoundedStravaJson at the two existing data call sites;
one no-throw exact-native unused-success-body cancellation helper;
the minimum expanded frozen, non-index-exported projector seam required by tests.
trustworthy RED and focused call-site/cancellation matrix;
direct preservation of impossible-JSON activity/statistics projector cases.
SECURITY.md
one separately named OAUTH-001A2L current-source/residual row immediately after OAUTH-001A2K.
No functions/index.js, browser/client, callback, disconnect/revoke, Firestore schema or Rules, package/lock, workflow, officer guide, provider setting, Firebase deployment, production data, or live behavior is included.
Trustworthy RED
On exact base b94622bd42775d84704d5fc05ee87da81f5a76e0, add one minimal test-only witness:
Seed the existing synthetic fresh connection/token.
Resolve both bearer fetches with genuine native responses and no Content-Length.
Activities emits one valid projected activity JSON document padded with trailing JSON whitespace in chunks of exactly 1 MiB and 1 byte.
Statistics has an ordinary valid native body and a cancellation hook.
Each response's own test-only json override delegates to native Response.prototype.text plus realm-local JSON parsing solely to prove the old source consumes the real streams.
Require the corrected source to read both activity chunks, return fixed data unavailable, cancel the activity reader once, cancel the unread statistics sibling once before any application statistics-body read, mixin invocation, decode, parse, or projection, preserve stored records, perform both bearer GETs, and make no writes/deletes/timestamps/logs. The statistics fixture may have an internally queued chunk; assert that its test-only json override and application read observer are not called.
Exact main must instead consume both complete bodies, return success, and cancel neither. Record the test-only binary diff hash and Node 20 focused output before implementation.
Add a symmetric successful-statistics overflow witness: ordinary bounded activities, then 64 KiB + 1 byte of valid padded statistics JSON; old source succeeds without cancellation, corrected source reads both chunks, cancels once, and returns fixed unavailable.
Required GREEN coverage
Reuse #614's generic reader matrix; do not duplicate it wholesale. Cover the two call sites and lifecycle:
below/exact/one-over each named cap;
absent, truthful, false-low, and declared-over-limit Content-Length at the call sites;
exact-body successful frozen output;
native .json() override and plain-success mock do not run/bypass;
malformed bytes/JSON stay fixed unavailable without raw details or logs;
activity HTTP admission, bounded-read, and schema failures each cancel an unread successful statistics sibling once;
sibling cancel throw, rejection, and never-settling promise cannot alter or delay the primary result;
locked/used/plain/Proxy/forged/non-success statistics siblings are not inspected through hostile traps and cleanup cannot replace the result;
pending activity EOF causes no statistics read, projection, result, write, or log;
statistics HTTP non-success remains optional and its body stays unread;
pending successful statistics EOF causes no early result;
statistics overflow/body failure self-cancels and is unavailable; bounded invalid schema is internal;
current successful refresh-CAS then data flow, ordinary fresh-token flow, response-status admission, and frozen result stay compatible;
no remaining production .json() at the activities/statistics call sites.
Do not delete or weaken existing Proxy, revoked Proxy, accessor, custom/null prototype, sparse array, BigInt/Symbol/NaN/Infinity, inherited/coercion, hostile fallback, unknown getter/symbol/cycle, exact-bound, logging, request, stored-token, refresh-CAS, status, or result-freeze coverage. JSON bytes cannot construct every hostile JavaScript value, so move those cases to direct snapshotProviderActivities / snapshotProviderStats seams that functions/index.js does not export.
This child handles the targeted unread statistics response only after both fetches fulfill. If either concurrent fetch rejects, current Promise.all destructuring may lose a fulfilled or later-fulfilled sibling response. Preserving fail-fast behavior while acquiring/canceling that later response belongs to a separately named transport/timeout child; do not switch to Promise.allSettled and wait indefinitely here.
Residuals also include request/connect/read deadlines and AbortSignal policy; headers; compressed wire bytes; Undici/socket buffering; one already-allocated chunk; parsed-object heap amplification; CPU; provider GET/rate-limit use already incurred before cancellation; legitimate above-budget provider drift; refresh/lost-ack reconciliation; scope/account policy; revoke/audit; IAM/encryption; Firebase deployment; provider configuration; production data; and live proof. This child deliberately preserves activity and statistics HTTP non-success bodies as unread and uncanceled; they may retain transport resources until Undici or the server cleans them up, and broader non-success-body disposal requires a separate compatibility review.
Acceptance criteria
Exact-base RED is reproducible and fails for the intended unbounded-read/no-sibling-cleanup reasons.
Both successful data-body call sites use the bounded native reader and their selected application caps.
Activity failures after both fetches resolve initiate only the targeted safe statistics cleanup without changing primary classification.
Impossible-JSON projector defenses remain directly tested, not deleted.
Exact-head security, resource-lifecycle, privacy/logging, test-quality, scope, and backup-officer reviews find no STOP.
PR and exact-main hosted CI pass; every deployment/live surface is recorded separately.
Officer impact: None — this server-only resource guard preserves existing member-visible activity/statistics success, optional-statistics, and fixed failure states within the selected budgets.
Officer documentation: None — no officer task, page structure, visible wording, data route, permission, account ownership, provider configuration, or deployment procedure changes. Existing Strava source-only/failure guidance remains current; no Mermaid change is needed.
Deployment evidence: None at issue creation. Source/tests/merge do not prove website publication, runmprc.com, Firebase deployment, provider configuration, production data, or live Strava behavior. Final evidence must record every surface separately.
Outcome
The Strava data callable must fully consume successful recent-activity and statistics replies through the merged bounded native JSON reader before projection or return. If activity admission fails after both fetch responses resolve, it must begin best-effort cancellation of the unread successful statistics body without waiting, logging, or changing the fixed activity result.
Parent: #88
Dependency: #614 / PR #615 merged exact main
b94622bd42775d84704d5fc05ee87da81f5a76e0.Explicit application-budget decision
Current projectors accept selected bounded fields while ignoring unknown fields. An otherwise accepted JSON object can therefore carry an arbitrarily large ignored string, polyline, numeric spelling, or additive field. No finite raw-body ceiling is mathematically backward-compatible with every value the old projector would accept.
Strava's official reference says the current calls return
SummaryActivity[]andActivityStats; this source requests five activities. The official schemas publish no response-byte,Content-Length, applicablemaxLength, or body-size guarantee. These are deliberately chosen MPRC application safety budgets, not provider guarantees:1,048,576content-decoded bytes (1 MiB) for the requested five summaries, allowing substantial margin for polylines and additive fields.65,536content-decoded bytes (64 KiB) for the current documented numeric statistics shape.4,096-chunk ceiling.A legitimate larger Strava reply will fail closed with the existing fixed unavailable result. Any cap change requires a separate reviewed change and redacted non-production evidence; source/tests here do not claim provider compatibility or live sizing.
Official references:
Invariant and allowed transitions
Responsefor activities, then use OAUTH-001A2K — Bound Strava OAuth token JSON responses before parsing #614's captured native stream reader with the 1 MiB ceiling.Content-Lengthis allowed. Canonical declared-over-limit length rejects early; false-low length cannot bypass actual-byte counting. Every chunk counts toward the shared 4,096 limit.unavailableresult. The reader cancels its unfinished activity body best-effort.internalresult.yearToDateandallTimenull.unavailable; bounded schema failure remains fixed datainternal; valid bounded data preserves the existing frozen result.json,text,arrayBuffer, orbytesmethod, clone, or tee. Plain test objects and overridden native mixins cannot bypass the boundary.Exact scope
functions/strava.jsreadBoundedStravaJsonat the two existing data call sites;functions/strava.test.jsResponse/ReadableStreamintegration fixtures;SECURITY.mdNo
functions/index.js, browser/client, callback, disconnect/revoke, Firestore schema or Rules, package/lock, workflow, officer guide, provider setting, Firebase deployment, production data, or live behavior is included.Trustworthy RED
On exact base
b94622bd42775d84704d5fc05ee87da81f5a76e0, add one minimal test-only witness:Content-Length.jsonoverride delegates to nativeResponse.prototype.textplus realm-local JSON parsing solely to prove the old source consumes the real streams.unavailable, cancel the activity reader once, cancel the unread statistics sibling once before any application statistics-body read, mixin invocation, decode, parse, or projection, preserve stored records, perform both bearer GETs, and make no writes/deletes/timestamps/logs. The statistics fixture may have an internally queued chunk; assert that its test-onlyjsonoverride and application read observer are not called.Exact main must instead consume both complete bodies, return success, and cancel neither. Record the test-only binary diff hash and Node 20 focused output before implementation.
Add a symmetric successful-statistics overflow witness: ordinary bounded activities, then 64 KiB + 1 byte of valid padded statistics JSON; old source succeeds without cancellation, corrected source reads both chunks, cancels once, and returns fixed unavailable.
Required GREEN coverage
Reuse #614's generic reader matrix; do not duplicate it wholesale. Cover the two call sites and lifecycle:
Content-Lengthat the call sites;.json()override and plain-success mock do not run/bypass;.json()at the activities/statistics call sites.Do not delete or weaken existing Proxy, revoked Proxy, accessor, custom/null prototype, sparse array, BigInt/Symbol/NaN/Infinity, inherited/coercion, hostile fallback, unknown getter/symbol/cycle, exact-bound, logging, request, stored-token, refresh-CAS, status, or result-freeze coverage. JSON bytes cannot construct every hostile JavaScript value, so move those cases to direct
snapshotProviderActivities/snapshotProviderStatsseams thatfunctions/index.jsdoes not export.Dependencies, split, and residuals
This child handles the targeted unread statistics response only after both fetches fulfill. If either concurrent fetch rejects, current
Promise.alldestructuring may lose a fulfilled or later-fulfilled sibling response. Preserving fail-fast behavior while acquiring/canceling that later response belongs to a separately named transport/timeout child; do not switch toPromise.allSettledand wait indefinitely here.Residuals also include request/connect/read deadlines and AbortSignal policy; headers; compressed wire bytes; Undici/socket buffering; one already-allocated chunk; parsed-object heap amplification; CPU; provider GET/rate-limit use already incurred before cancellation; legitimate above-budget provider drift; refresh/lost-ack reconciliation; scope/account policy; revoke/audit; IAM/encryption; Firebase deployment; provider configuration; production data; and live proof. This child deliberately preserves activity and statistics HTTP non-success bodies as unread and uncanceled; they may retain transport resources until Undici or the server cleans them up, and broader non-success-body disposal requires a separate compatibility review.
Acceptance criteria
Officer impact: None — this server-only resource guard preserves existing member-visible activity/statistics success, optional-statistics, and fixed failure states within the selected budgets.
Officer documentation: None — no officer task, page structure, visible wording, data route, permission, account ownership, provider configuration, or deployment procedure changes. Existing Strava source-only/failure guidance remains current; no Mermaid change is needed.
Deployment evidence: None at issue creation. Source/tests/merge do not prove website publication,
runmprc.com, Firebase deployment, provider configuration, production data, or live Strava behavior. Final evidence must record every surface separately.