Console granted-user sign-in, a user-cli transport per session, the per-request grant re-read, the owner-only gate and user page, the notice, the hub label and peer links, accessContextFor peers, and the bus boot access wiring (sage-3142). Tests G1-G8 and B1-B3 are written and not yet run; runs wait for Sage's CLEAR. Choices C1-C9 in agents/launchpad/work/queue-294/BUILD.md.
27 lines
1.6 KiB
JavaScript
27 lines
1.6 KiB
JavaScript
// FED R6 (#1800, federation design 3.1 D3 and D5): who besides the owner may sign in to this
|
|
// Console. `load` is R1's loadAccess over this instance's access.json and context, called on every
|
|
// use and never cached, so a revoke, a removed subject or an expired grant counts on the next
|
|
// request. A user is live while one grant in the Console's business covers at `viewer`, the same
|
|
// test as the broker's #userGrants. The broker still decides every verb, project, instance and
|
|
// thread (D4). Any failure to load, or to name the business, finds nobody (fail closed).
|
|
import { covers } from '../../business/src/vocabulary.mjs';
|
|
|
|
export function consoleAccess({ load, business }) {
|
|
if (typeof load !== 'function' || typeof business !== 'function') throw new TypeError('consoleAccess needs load and business functions');
|
|
const live = (doc, id, b) => doc.grants.some(g => g.user === id && g.business === b &&
|
|
covers(g, { business: b, project: g.projects[0], instance: g.instances[0] }, new Date(), { level: 'viewer' }));
|
|
const lookup = (provider, sub) => {
|
|
try {
|
|
const doc = load(), b = business();
|
|
const user = doc.users.find(u => u.subjects.some(s => s.provider === provider && s.sub === sub));
|
|
return user && live(doc, user.id, b) ? user.id : null;
|
|
} catch { return null; }
|
|
};
|
|
return Object.freeze({
|
|
// The user id this (provider, sub) signs in as, or null.
|
|
find: ({ provider, sub }) => lookup(provider, sub),
|
|
// Is this session's user still the holder of its own subject, with a live grant?
|
|
check: session => typeof session?.user === 'string' && lookup(session.provider, session.sub) === session.user,
|
|
});
|
|
}
|