Changeset d56d471 in Klonkt for src/services/guardianship/gated.js
- Timestamp:
- 07/29/2026 12:36:50 PM (6 weeks ago)
- Branches:
- main
- Children:
- 7a93fcf
- Parents:
- 6100ce9
- File:
-
- 1 edited
-
src/services/guardianship/gated.js (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/guardianship/gated.js
r6100ce9 rd56d471 182 182 export function clearGatedReviews(id) { rstmts().delAll.run(id); } 183 183 184 export function rememberGatedOffer(offerId, slug, feature, value ) {184 export function rememberGatedOffer(offerId, slug, feature, value, proposer) { 185 185 try { 186 db.prepare('INSERT OR REPLACE INTO ap_gated_offers (offer_id, slug, feature, value ) VALUES (?,?,?,?)')187 .run(offerId, slug, feature, value ? 1 : 0 );186 db.prepare('INSERT OR REPLACE INTO ap_gated_offers (offer_id, slug, feature, value, proposer) VALUES (?,?,?,?,?)') 187 .run(offerId, slug, feature, value ? 1 : 0, proposer || null); 188 188 } catch { /* non-fatal */ } 189 189 } … … 192 192 try { return db.prepare('SELECT * FROM ap_gated_offers WHERE offer_id = ?').get(offerId) || null; } 193 193 catch { return null; } 194 } 195 196 // ── The proposer's own record (5.6) ─────────────────────────────── 197 // "Where did my proposal go?" had no answer: the status was a button caption 198 // that did not survive a refresh. The ward's server tallies elsewhere, so the 199 // proposer keeps its own row and the ward's server ANSWERS the Offer when the 200 // decision settles: Accept when it settled on the proposed value, Reject when 201 // it settled on the opposite. An open row past the window renders as expired, 202 // because an expired decision settles on nothing and nobody writes home. 203 204 export function recordSent(offerId, guardianSlug, wardUri, feature, value) { 205 try { 206 db.prepare(`INSERT OR REPLACE INTO ap_gated_sent (offer_id, guardian_slug, ward_uri, feature, value) 207 VALUES (?,?,?,?,?)`).run(offerId, guardianSlug, wardUri, feature, value ? 1 : 0); 208 } catch { /* non-fatal */ } 209 } 210 211 export function recallSent(offerId) { 212 try { return db.prepare('SELECT * FROM ap_gated_sent WHERE offer_id = ?').get(offerId) || null; } 213 catch { return null; } 214 } 215 216 export function settleSent(offerId, outcome) { 217 try { db.prepare('UPDATE ap_gated_sent SET status = ? WHERE offer_id = ?').run(outcome, offerId); } catch { /* non-fatal */ } 218 } 219 220 /** The latest proposal per feature this guardian sent to this ward. */ 221 export function listSent(guardianSlug, wardUri) { 222 try { 223 return db.prepare(`SELECT * FROM ap_gated_sent WHERE guardian_slug = ? AND ward_uri = ? 224 GROUP BY feature HAVING MAX(created_at) ORDER BY created_at DESC`).all(guardianSlug, wardUri); 225 } catch { return []; } 226 } 227 228 /** 229 * What a sent row means on a screen. Pure, so the rule is testable: an answer 230 * wins, and silence past the window is not "still running", it is over. 231 */ 232 export function sentStatus(row, now) { 233 if (!row) return null; 234 if (row.status === 'accepted' || row.status === 'rejected') return row.status; 235 const opened = new Date(String(row.created_at).includes('T') ? row.created_at : `${row.created_at}Z`.replace(' ', 'T')).getTime(); 236 if (Number.isFinite(opened) && now - opened >= GATED_WINDOW_MS) return 'expired'; 237 return 'open'; 194 238 } 195 239 … … 198 242 parseGatedSetting, buildGatedOffer, rememberGatedOffer, recallGatedOffer, 199 243 recordGatedReview, getGatedReview, listGatedReviews, removeGatedReview, clearGatedReviews, 244 recordSent, recallSent, settleSent, listSent, sentStatus, 200 245 };
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)