Fix SVG dataset crash and 403 on intent API

- Remove `dataset = {}` assignment on SVG circle element (read-only
  property on SVGElement, causes TypeError crash on every render)
- Add authHeaders() helper using encryptid-token from localStorage
- Include Authorization header on all mutating intent API calls
  (create, solver/run, accept, reject)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-31 23:17:14 -07:00
parent 2907935c50
commit 1dcc3ff0a1
1 changed files with 11 additions and 5 deletions

View File

@ -323,6 +323,12 @@ class FolkTimebankApp extends HTMLElement {
return match ? match[0] : '/rtime';
}
/** Auth headers from encryptid session token. */
private authHeaders(): Record<string, string> {
const token = localStorage.getItem('encryptid-token');
return token ? { Authorization: `Bearer ${token}` } : {};
}
disconnectedCallback() {
if (this.animFrame) cancelAnimationFrame(this.animFrame);
}
@ -968,7 +974,7 @@ class FolkTimebankApp extends HTMLElement {
portHit.setAttribute('cx', String(pts[1][0])); portHit.setAttribute('cy', String(pts[1][1]));
portHit.setAttribute('r', '18'); portHit.setAttribute('fill', 'transparent');
portHit.setAttribute('class', 'port');
(portHit as any).dataset = {}; portHit.setAttribute('data-node', node.id); portHit.setAttribute('data-port', 'output');
portHit.setAttribute('data-node', node.id); portHit.setAttribute('data-port', 'output');
g.appendChild(portHit);
const port = ns('circle');
port.setAttribute('cx', String(pts[1][0])); port.setAttribute('cy', String(pts[1][1]));
@ -1458,7 +1464,7 @@ class FolkTimebankApp extends HTMLElement {
try {
const resp = await fetch(`${this.getApiBase()}/api/intent`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: { 'Content-Type': 'application/json', ...this.authHeaders() },
body: JSON.stringify({ type, skill, hours, description }),
});
if (!resp.ok) {
@ -1475,7 +1481,7 @@ class FolkTimebankApp extends HTMLElement {
private async triggerSolver() {
try {
await fetch(`${this.getApiBase()}/api/solver/run`, { method: 'POST' });
await fetch(`${this.getApiBase()}/api/solver/run`, { method: 'POST', headers: this.authHeaders() });
this.refreshCollaborate();
} catch {
// ignore
@ -1607,7 +1613,7 @@ class FolkTimebankApp extends HTMLElement {
btn.addEventListener('click', async () => {
const resultId = (btn as HTMLElement).dataset.resultId;
try {
await fetch(`${this.getApiBase()}/api/solver-results/${resultId}/accept`, { method: 'POST' });
await fetch(`${this.getApiBase()}/api/solver-results/${resultId}/accept`, { method: 'POST', headers: this.authHeaders() });
this.refreshCollaborate();
} catch { /* ignore */ }
});
@ -1617,7 +1623,7 @@ class FolkTimebankApp extends HTMLElement {
btn.addEventListener('click', async () => {
const resultId = (btn as HTMLElement).dataset.resultId;
try {
await fetch(`${this.getApiBase()}/api/solver-results/${resultId}/reject`, { method: 'POST' });
await fetch(`${this.getApiBase()}/api/solver-results/${resultId}/reject`, { method: 'POST', headers: this.authHeaders() });
this.refreshCollaborate();
} catch { /* ignore */ }
});