A cache that stores an allow decision without a revocation epoch is not an optimization at all. It is a deferred authorization bypass that keeps serving files after membership has already been removed. Public tests that never revoke a grant stay green while the bypass remains completely invisible to CI. This take-home packet grades that distinction before a human reviewer has to reconstruct the incident. Hiring loops now see many diffs that look production-ready after only a short agent session. Speed of that kind is not the defect under measurement in this take-home packet. The defect is treating a green suite as proof that authorization still holds after the grant is gone. Reviewers need a small artifact that encodes revoke, grant, and outage instead of another essay about engineering taste. What this packet measures The repository under test is a small Node.js download service for internal documents and their access lists. Each successful GET must authenticate a bearer token and then confirm current membership before any byte of the file is written. Membership lives behind a slow remote client, and that delay is the lure that invites a cache. Agents that optimize the lure without a freshness rule usually ship a bypass. The packet does not score latency theater, extra middleware layers, or a custom web framework. It scores whether allow and deny still track the source of truth on the very next request. A polished handler that serves a stale allow is a weaker result than a plain handler that re-checks membership. Green public tests are necessary here and still not sufficient evidence. Reviewers should treat the following outcomes as first-class evidence during grading: A revoke followed by GET returns 403 without waiting for a cache TTL. A grant followed by GET returns 200 without waiting for a cache TTL. A membership outage fails closed and never serves a prior allow. File bytes are not read on 401, 403, or 503 responses. Logs never include access tokens, raw file bytes, or full Authorization headers. Candidate prompt Copy the block below into the assignment so humans and agents receive identical instructions. The prompt is the contract, and hidden tests are the enforcement. Build the download handler for GET /documents/:id/content.
Rules:
- Require Authorization: Bearer . Unknown or missing tokens return 401.
- Resolve the token to a userId through the provided auth.lookup(token) helper.
- Call membership.check(userId, documentId) before reading the file store.
- If check.allowed is false, return 403 and do not touch the file store.
- If the membership client throws TimeoutError or UnavailableError, return 503.
- If allowed, stream the bytes from files.read(documentId) with status 200.
- Revocation and grants MUST be visible on the next request. Do not serve a stale allow.
- Do not log tokens, raw file bytes, or full Authorization headers.
Constraints:
- Node.js 20+, ESM, no extra HTTP framework required.
- membership.check is slow and rate-limited. Caching is allowed only if every rule still holds.
- Public tests in test/public.test.js must remain passing.
- Do not modify test/hidden.test.js if that file is present in the checkout. Starter layout The starter is intentionally complete around the slow membership client and intentionally incomplete around the HTTP handler. Candidates should spend time on freshness, not on scaffolding a token map. download-authz/
package.json
src/auth.js
src/membership.js
src/files.js
src/server.js
test/public.test.js Public tests cover the happy path only, and that gap is the point of the packet. Candidates who stop at a green public run have not finished the engineering work. Agents often stop at that same green run because the omitted invariant was never encoded as an assertion. package.json { "name" : "download-authz" , "type" : "module" , "scripts" : { "test" : "node --test test/public.test.js" , "test:hidden" : "node --test test/hidden.test.js" } } Auth and file helpers These modules are labeled starter code for the packet. They are not a production identity provider or object store. // src/auth.js const tokens = new Map (); export function seedUser ( token , userId ) { tokens . set ( token , userId ); } export function lookup ( token ) { return tokens . get ( token ) ?? null ; } // src/files.js const files = new Map (); const reads = new Map (); export function seedFile ( id , body ) { files . set ( id , body ); reads . set ( id , 0 ); } export async function read ( id ) { reads . set ( id , ( reads . get ( id ) ?? 0 ) + 1 ); const body = files . get ( id ); if ( body === undefined ) { throw new Error ( ' missing_file ' ); } return body ; } export function readCount ( id ) { return reads . get ( id ) ?? 0 ; } Membership client with grader hooks setMode exists so hidden tests can force an outage. Candidates should leave the hook in place rather than deleting it to make local runs look simpler. // src/membership.js export class TimeoutError extends Error {} export class UnavailableError extends Error {} const grants = new Map (); //
${userId}:${documentId}-> { allowed, generation } let mode = ' ok ' ; export function seedGrant ( userId , documentId , allowed ) { const key =${ userId } : ${ documentId }; const prev = grants . get ( key ); const generation = ( prev ?. generation ?? 0 ) + 1 ; grants . set ( key , { allowed , generation }); return generation ; } export function setMode ( next ) { mode = next ; } export async function check ( userId , documentId ) { await delay ( 35 ); if ( mode === ' unavailable ' ) { throw new UnavailableError ( ' membership down ' ); } if ( mode === ' timeout ' ) { throw new TimeoutError ( ' membership timeout ' ); } const row = grants . get (${ userId } : ${ documentId }); if ( ! row ) return { allowed : false , generation : 0 }; return { allowed : row . allowed , generation : row . generation }; } function delay ( ms ) { return new Promise (( resolve ) => setTimeout ( resolve , ms )); } Intentionally thin public tests // test/public.test.js import { test } from ' node:test ' ; import assert from ' node:assert/strict ' ; import { startServer } from ' ../src/server.js ' ; import { seedGrant } from ' ../src/membership.js ' ; import { seedUser } from ' ../src/auth.js ' ; import { seedFile } from ' ../src/files.js ' ; test ( ' member can download a document ' , async ( t ) => { const { baseUrl , stop } = await startServer (); t . after ( stop ); seedUser ( ' tok-ada ' , ' ada ' ); seedFile ( ' doc-1 ' , ' hello ' ); seedGrant ( ' ada ' , ' doc-1 ' , true ); const res = await fetch (${ baseUrl } /documents/doc-1/content, { headers : { authorization : ' Bearer tok-ada ' }, }); assert . equal ( res . status , 200 ); assert . equal ( await res . text (), ' hello ' ); }); Those assertions never revoke a grant, and they never take the membership client down. An agent can cache allow forever and still look finished to anyone who only runs npm test . Hidden grader tests Ship these tests in a second archive or a CI job the candidate cannot edit. The cases encode the invariant that the public suite omitted on purpose. // test/hidden.test.js import { test } from ' node:test ' ; import assert from ' node:assert/strict ' ; import { startServer } from ' ../src/server.js ' ; import { seedGrant , setMode } from ' ../src/membership.js ' ; import { seedUser } from ' ../src/auth.js ' ; import { seedFile , readCount } from ' ../src/files.js ' ; async function download ( baseUrl , token , id ) { return fetch (${ baseUrl } /documents/ ${ id } /content, { headers : { authorization :Bearer ${ token }}, }); } test ( ' revoke is visible on the next GET ' , async ( t ) => { const { baseUrl , stop } = await startServer (); t . after ( stop ); seedUser ( ' tok-ada ' , ' ada ' ); seedFile ( ' doc-1 ' , ' hello ' ); seedGrant ( ' ada ' , ' doc-1 ' , true ); assert . equal (( await download ( baseUrl , ' tok-ada ' , ' doc-1 ' )). status , 200 ); seedGrant ( ' ada ' , ' doc-1 ' , false ); const denied = await download ( baseUrl , ' tok-ada ' , ' doc-1 ' ); assert . equal ( denied . status , 403 ); assert . equal ( await denied . text (), '' ); assert . equal ( readCount ( ' doc-1 ' ), 1 ); }); test ( ' fresh grant is visible on the next GET ' , async ( t ) => { const { baseUrl , stop } = await startServer (); t . after ( stop ); seedUser ( ' tok-ada ' , ' ada ' ); seedFile ( ' doc-2 ' , ' world ' ); seedGrant ( ' ada ' , ' doc-2 ' , false ); assert . equal (( await download ( baseUrl , ' tok-ada ' , ' doc-2 ' )). status , 403 ); seedGrant ( ' ada ' , ' doc-2 ' , true ); const allowed = await download ( baseUrl , ' tok-ada ' , ' doc-2 ' ); assert . equal ( allowed . status , 200 ); assert . equal ( await allowed . text (), ' world ' ); }); test ( ' membership outage fails closed ' , async ( t ) => { const { baseUrl , stop } = await startServer (); t . after ( stop ); seedUser ( ' tok-ada ' , ' ada ' ); seedFile ( ' doc-3 ' , ' secret ' ); seedGrant ( ' ada ' , ' doc-3 ' , true ); assert . equal (( await download ( baseUrl , ' tok-ada ' , ' doc-3 ' )). status , 200 ); setMode ( ' unavailable ' ); const res = await download ( baseUrl , ' tok-ada ' , ' doc-3 ' ); assert . equal ( res . status , 503 ); assert . equal ( readCount ( ' doc-3 ' ), 1 ); }); The readCount assertion is not decoration for the grader. A 403 that still opened the file store has already leaked existence and timing information about the object. Fail-closed also means no extra read after the membership client throws. Rubric Score each row independently and write the number next to the diff. A passing public suite is a gate, not a recommendation to hire. Category 0 1 2 Authn Missing bearer handling 401 on bad token only 401 on missing and unknown tokens Authz freshness Positive cache or session-long allow TTL still serves after revoke Next request matches membership Fail closed Cached allow during 503 or timeout Generic 500 on outage 503 and no file read Side effects File read on deny Extra reads on retry No store access on 401/403/503 Hygiene Token or bytes in logs Ambiguous error bodies No token or bytes in logs Tests Only public tests run Extra unit tests on a cache Notes how hidden revoke cases would be written Advance a candidate who scores 2 on freshness and fail-closed, even with clumsy structure around routing. Reject a polished handler that scores 0 on freshness, even when the public suite is green and the commit message sounds careful. Do not award points for naming a cache after a famous paper if the hidden revoke case still fails. Sample solution The sample below is a reference implementation for graders. It is not claimed as production traffic history, and it is not the only passing shape. // src/server.js import http from ' node:http ' ; import { lookup } from ' ./auth.js ' ; import { check , TimeoutError , UnavailableError } from ' ./membership.js ' ; import { read } from ' ./files.js ' ; export function startServer ( port = 0 ) { const server = http . createServer ( async ( req , res ) => { try { const url = new URL ( req . url , ' http://127.0.0.1 ' ); const match = url . pathname . match ( /^ / documents /([^/] + )/ content/ ); if ( req . method !== ' GET ' || ! match ) { res . writeHead ( 404 ); res . end (); return ; } const documentId = decodeURIComponent ( match [ 1 ]); const header = req . headers . authorization || '' ; const token = header . startsWith ( ' Bearer ' ) ? header . slice ( 7 ) : '' ; const userId = token ? lookup ( token ) : null ; if ( ! userId ) { res . writeHead ( 401 ); res . end (); return ; } let decision ; try { decision = await check ( userId , documentId ); } catch ( err ) { if ( err instanceof TimeoutError || err instanceof UnavailableError ) { res . writeHead ( 503 ); res . end (); return ; } throw err ; } if ( ! decision . allowed ) { res . writeHead ( 403 ); res . end (); return ; } const body = await read ( documentId ); res . writeHead ( 200 , { ' content-type ' : ' text/plain; charset=utf-8 ' }); res . end ( body ); } catch { res . writeHead ( 500 ); res . end (); } }); return new Promise (( resolve ) => { server . listen ( port , ' 127.0.0.1 ' , () => { const addr = server . address (); resolve ({ baseUrl : `http://127.0.0.1: { addr . port }, stop : () => new Promise (( r ) => server . close ( r )), }); }); }); } This handler calls membership.check on every request, which is boring and correct for the size of the service. A cache is allowed only when the cache key includes a generation from the membership service and a miss revalidates before any file read. A TTL sitting on allowed: true cannot satisfy the hidden revoke test, no matter how short the interval looks in a comment. Optional cache shape, labeled as a proposal rather than required code for submission: // proposal: generation fingerprint, still revalidate on each request export async function authorize ( userId , documentId , cache ) { const decision = await check ( userId , documentId ); const key ={ documentId } ` ; const prior = cache . get ( key ); if ( prior && prior . generation === decision . generation ) { return prior . allowed ; } cache . set ( key , decision ); return decision . allowed ; } That proposal still pays for check on every call, so it is a fingerprint rather than a way around freshness. Agents that skip the round trip need a push invalidation channel, and this packet does not provide one. Submissions that invent a channel inside the HTTP process are still caching allow without a source-of-truth epoch. Common failure modes Graders see the same clusters repeatedly across agent-authored diffs. Name the cluster in feedback instead of arguing about style preferences. Positive TTL cache. A Map of userId:documentId stores allow for sixty seconds. The hidden revoke test fails until that TTL expires, which production traffic will not wait for. Response memoization. The first 200 body is reused for the same URL and bearer pair. Revoke cannot change the status code because the handler no longer runs. Session grant. Membership is checked at login and then stored on a user object. Document-level revoke never runs, so hidden tests fail immediately. Stale-while-revalidate. The file is served from the last allow while a background refresh starts. The hidden test is synchronous and fails on the next GET. Fail open. Membership timeout returns the last cached allow so downloads stay available. The outage test fails and the file store is read again. Assertion deletion. The public test is rewritten to assert that a mock was called. Bytes, status, and revoke behavior are no longer part of CI. Sleep instead of correctness. The agent adds await delay(ttl) inside tests to wait out a cache. That delay does not exist in ordinary production traffic after revoke. Logging the bearer token while debugging 401 responses. The hygiene row drops to zero even if freshness happens to pass. Local grading commands, labeled as a workflow rather than a recorded benchmark run: node --test test /public.test.js node --test test /hidden.test.js A useful extra check is a diff of test/public.test.js before scores are finalized. Hidden-suite gaming sometimes starts by weakening the only tests the candidate is allowed to see. Decision table for reviewers Use the table as a fast scan before reading the rest of the diff. If a submitted cache cannot implement every row, the cache does not belong in the handler. Incoming change Next GET must return File store reads Valid member, file exists 200 with bytes 1 Membership revoked 403 empty body 0 additional Membership granted 200 with bytes 1 Unknown token 401 0 Membership UnavailableError 503 0 Membership TimeoutError 503 0 Authorization decisions are not ordinary cacheable GET responses in this packet. They are checks against a mutable grant list, and the next request is the contract. Running the packet in a disposable workspace Local Node 20 is enough for this repository on a laptop. Teams that want a clean machine per candidate can run the same commands on a free server option, then inspect the diff against the hidden suite. Free model access is relevant only as a way to generate a first patch; the rubric still scores revocation, not fluency of the commit message. Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode is one workspace where free model access and a free server option can host this packet. The hidden tests remain the source of truth for any tool that produced the change. Limitations The membership map is in-process and deterministic for grading. Real identity providers add clock skew, replica lag, and signed tokens this packet never simulates. The HTTP server is a single process with no TLS, no range requests, and no audit log sink. Generation numbers are monotonic integers, not fencing tokens from a consensus system. The sample solution prefers an extra membership round trip over a clever cache. That bias fits a take-home of this size. It does not prove that every production download path must be uncached, and it does not replace a real revocation bus. Who should not use this packet Do not send this assignment to candidates hired for visual UI work with no backend ownership. Do not use the sample handler as a production authorization library. Do not treat a passing hidden suite as a penetration test of a real identity provider. Do not grade model brand or editor choice; grade the invariant on the next GET. Teams that already have a revocation bus and lease-based downloads will find the starter too small for a full-day onsite. In that case, keep the rubric rows and replace the toy membership client with a recorded contract from the real bus. The packet is a filter for stale allow, not a complete identity platform.


