A guest login is a full account with a clock on it
Mitchell, on the read-only version built earlier today: scratch it. He hands these to people he trusts and revokes them otherwise, so a console with half its tabs missing solved a problem he doesn't have. So the allow-list, the middleware check and every "not for a guest" branch in the UI are gone. What is left is the part that was the point: a throwaway account that expires by itself, is checked on every request, swept once a minute, and can be ended in one tap. A guest now gets the whole console on every machine, terminal included. Said once, since it is his call and he has made it: that means a guest has a root-capable shell on every host, and can make an account or a token of its own that outlives the guest login. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8a7167bf03
commit
179f342a2c
+1
-9
@@ -1,12 +1,5 @@
|
||||
import { isGuest } from './guest'
|
||||
|
||||
export class Unauthenticated extends Error { constructor(msg = 'unauthenticated') { super(msg) } }
|
||||
|
||||
// What a guest login may send. Everything else that would change something is refused here
|
||||
// as well as by the server, so a button a page forgot to hide fails without a round trip.
|
||||
const GUEST_WRITES = new Set(['POST /api/logout', 'PUT /api/prefs/ui'])
|
||||
export const guestRefusal = 'a guest login can only look around'
|
||||
|
||||
// Which machine the console is looking at. '' is this host; otherwise every /api/… call
|
||||
// is rewritten to /api/nodes/<name>/… and the hub proxies it. Hub-only calls (login,
|
||||
// the machine list itself) pass local=true and are never rewritten.
|
||||
@@ -26,7 +19,6 @@ function track(delta: number) {
|
||||
}
|
||||
|
||||
async function req<T>(method: string, path: string, body?: unknown, local = false): Promise<T> {
|
||||
if (isGuest() && method !== 'GET' && !GUEST_WRITES.has(`${method} ${path}`)) throw new Error(guestRefusal)
|
||||
const target = local ? path : apiPath(path)
|
||||
const mach = machineOf(target)
|
||||
if (mach && downUntil[mach] > Date.now()) throw new Error(`${mach} unreachable (retrying shortly)`)
|
||||
@@ -166,7 +158,7 @@ export interface UIPrefs { theme?: string; refreshMs?: number; accents?: Record<
|
||||
export interface User { name: string; created: string; last_seen?: string; sessions: number; self: boolean }
|
||||
export interface Session { id: string; created: string; last_seen: string; expires: string; ip?: string; agent?: string; current: boolean }
|
||||
export interface TokenInfo { name: string; created: string; scope?: string; sensors?: string[]; issued_by?: string }
|
||||
// A guest login: temporary, look-only, gone at `expires` or when revoked.
|
||||
// A guest login: a full account with a clock on it, gone at `expires` or when revoked.
|
||||
export interface Guest { name: string; created: string; expires: string; issued_by?: string; sessions: number; used: boolean }
|
||||
export interface FreshGuest { name: string; password: string; expires: string; minutes: number }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user