@@ -30974,8 +30974,6 @@ function state_readState() {
3097430974 try {
3097530975 const content = external_fs_namespaceObject.readFileSync(statePath, 'utf-8');
3097630976 const parsed = JSON.parse(content);
30977- // TODO: Validate parsed state has correct shape
30978- // For now, trust the structure
3097930977 if (!isValidState(parsed)) {
3098030978 return {
3098130979 success: false,
@@ -31064,6 +31062,12 @@ function isValidState(obj) {
3106431062 if (typeof obj['poll_failures'] !== 'number') {
3106531063 return false;
3106631064 }
31065+ // Validate each bucket entry
31066+ for (const value of Object.values(obj['buckets'])) {
31067+ if (!isValidBucketState(value)) {
31068+ return false;
31069+ }
31070+ }
3106731071 // Optional fields: must be string | null
3106831072 if (!isStringOrNull(obj['stopped_at_ts'])) {
3106931073 return false;
@@ -31076,6 +31080,34 @@ function isValidState(obj) {
3107631080 }
3107731081 return true;
3107831082}
31083+ /**
31084+ * Validates that a value has the BucketState shape.
31085+ */
31086+ function isValidBucketState(value) {
31087+ if (!isARealObject(value)) {
31088+ return false;
31089+ }
31090+ const numericFields = [
31091+ 'last_reset',
31092+ 'last_used',
31093+ 'total_used',
31094+ 'windows_crossed',
31095+ 'anomalies',
31096+ 'limit',
31097+ 'remaining',
31098+ 'first_used',
31099+ 'first_remaining',
31100+ ];
31101+ for (const field of numericFields) {
31102+ if (typeof value[field] !== 'number') {
31103+ return false;
31104+ }
31105+ }
31106+ if (typeof value['last_seen_ts'] !== 'string') {
31107+ return false;
31108+ }
31109+ return true;
31110+ }
3107931111// -----------------------------------------------------------------------------
3108031112// PID file management
3108131113// -----------------------------------------------------------------------------
@@ -31255,8 +31287,7 @@ function spawnPoller(token) {
3125531287 const baseDir = actionPath
3125631288 ? external_path_namespaceObject.resolve(actionPath, 'dist')
3125731289 : external_path_namespaceObject.dirname(process.argv[1] ?? '');
31258- const separator = baseDir.endsWith(external_path_namespaceObject.sep) ? '' : external_path_namespaceObject.sep;
31259- const pollerEntry = `${baseDir}${separator}poller${external_path_namespaceObject.sep}index.js`;
31290+ const pollerEntry = external_path_namespaceObject.join(baseDir, 'poller', 'index.js');
3126031291 const child = (0,external_child_process_namespaceObject.spawn)(process.execPath, [pollerEntry], {
3126131292 detached: true,
3126231293 stdio: 'ignore',
@@ -31883,7 +31914,7 @@ function parseRateLimitResponse(raw) {
3188331914 const resources = {};
3188431915 for (const [key, value] of Object.entries(raw['resources'])) {
3188531916 if (!isValidSample(value)) {
31886- return null;
31917+ continue; // Skip invalid resources instead of failing the entire response
3188731918 }
3188831919 resources[key] = value;
3188931920 }
0 commit comments