#64 keys the write limit per caller: a signed-in write spends its forge id's bucket, a guest's spends server.requestIP(request)?.address. That is exactly right for a signed-in person, and it is the only unforgeable option for a guest — a forwarded-for header is a header the client wrote, and trusting one would undo the whole point.
The catch is that the app listens on 127.0.0.1 and the forge proxies to it, so the socket address every guest request arrives on is very likely the proxy's, not the visitor's. If so, all guests on a deployment share one key ip:<proxy address>, and one guest running 300 writes a minute refuses every other guest's writes (signed-in people are unaffected — they key by id). That is far better than before #64, where one anonymous caller could refuse everyone, but it is not yet the per-person fairness the README now describes for guests.
Two steps:
Check what the app actually sees. Log server.requestIP(request)?.address once for a request arriving through the preview's public URL and compare it with the visitor's address. If they differ, the README's "a guest's by the connecting socket address" is misleading and should say so plainly.
If they differ, the honest fix needs the forge, not a header: a signed client address (the same HMAC shape as x-forge-identity, verified in src/who.ts) would make a guest's real address as trustworthy as a forge id. Failing that, keep the socket key but consider a smaller guest allowance per board, so a shared guest bucket cannot be drained by one tab.
Found while reviewing #64, which I approved — this is the residue of that design, not a fault in it.
#64 keys the write limit per caller: a signed-in write spends its forge id's bucket, a guest's spends
server.requestIP(request)?.address. That is exactly right for a signed-in person, and it is the only unforgeable option for a guest — a forwarded-for header is a header the client wrote, and trusting one would undo the whole point.The catch is that the app listens on
127.0.0.1and the forge proxies to it, so the socket address every guest request arrives on is very likely the proxy's, not the visitor's. If so, all guests on a deployment share one keyip:<proxy address>, and one guest running 300 writes a minute refuses every other guest's writes (signed-in people are unaffected — they key by id). That is far better than before #64, where one anonymous caller could refuse everyone, but it is not yet the per-person fairness the README now describes for guests.Two steps:
server.requestIP(request)?.addressonce for a request arriving through the preview's public URL and compare it with the visitor's address. If they differ, the README's "a guest's by the connecting socket address" is misleading and should say so plainly.x-forge-identity, verified insrc/who.ts) would make a guest's real address as trustworthy as a forge id. Failing that, keep the socket key but consider a smaller guest allowance per board, so a shared guest bucket cannot be drained by one tab.Found while reviewing #64, which I approved — this is the residue of that design, not a fault in it.