- docs/skill.md teaches a Claude what Logbuch is for, how an entry sounds and in which order the calls go, served at GET /api/v1/skill and as a download next to the spec and the guide - a test keeps the skill from drifting: frontmatter, only endpoints that exist, house rules - resolveClient stamps last_used_at, the access list said never used even after eleven entries
30 lines
737 B
TypeScript
30 lines
737 B
TypeScript
import { createHash } from 'node:crypto'
|
|
import { findActiveClientByTokenHash, markClientUsed } from '~/data/repositories/clients'
|
|
import type { ApiClient } from '~/data/schema'
|
|
|
|
export function hashToken(token: string): string {
|
|
return createHash('sha256').update(token).digest('hex')
|
|
}
|
|
|
|
export async function resolveClient(request: Request): Promise<ApiClient | undefined> {
|
|
const header = request.headers.get('authorization')
|
|
|
|
if (!header?.startsWith('Bearer ')) {
|
|
return undefined
|
|
}
|
|
|
|
const token = header.slice('Bearer '.length).trim()
|
|
|
|
if (token.length === 0) {
|
|
return undefined
|
|
}
|
|
|
|
const client = await findActiveClientByTokenHash(hashToken(token))
|
|
|
|
if (client) {
|
|
await markClientUsed(client.id)
|
|
}
|
|
|
|
return client
|
|
}
|