Component · for humans & their agents
Portal Access Offboarding
verified · first-partyactively maintained$0 during beta (was $59)
The client left. The link still works. Finds client-portal access that outlived the relationship, and revokes the whole trail of it rather than the one link you remember.
by saltyhash · Code Recycle admin
18 tests · 3/3 deliberate defects caught. Zero runtime dependencies.
The defect
Agencies, law firms, accountants and property managers all build the same portal, and access is a link — a signed URL, a magic link, an invite token. That link is a bearer credential: whoever holds it is the client.
Then the engagement ends. The client is offboarded in the CRM, removed from the project, marked inactive. The link keeps working, because it was never connected to the relationship. No error, no alert, and no screen anywhere listing "people who can still see your files". The usual way this is discovered is a forwarded email, months later.
auditGrants(grants, { now, relationships: { c1: "ended" } });
// [{ severity: "critical", problems: ["outlived_relationship"],
// detail: "the client relationship is ended, but this grant still opens …" }]Revoke the set, not the link
A three-year engagement leaves a trail: the original invite, a re-send after someone lost it, one issued to the client's accountant, one pasted into a Slack channel. Revoking the link revokes one of them.
grantsToRevoke(grants, "c1", now); // every live grant for that clientAn unknown client is treated as ENDED
The relationship map comes from your CRM. The realistic reason a client is missing from it is that the record was deleted or the export missed it — **exactly the cases where access should have been cut.** Defaulting unknown to "active" would make the audit quietest on the records that fell out of the system, which is where the risk actually is.
Where the token sits
| placement | verdict | |---|---| | query (?token=…) | flagged | | fragment, header, cookie | fine |
A token in the query string leaks in ways nobody intends: the Referer header sends the full URL to every third-party asset on the page, and it lands in server access logs, analytics, browser history, and whatever the client pastes into an email. The fragment is never transmitted to the server at all.
Also flagged: grants with no expiry, links needing no sign-in (forwarding the link forwards the access), and long-dormant grants — where revoking costs nobody anything.
What it does not do
| not included | why | |---|---| | Issuing, storing or revoking grants | it reads your grant records and tells you which to kill | | Authentication | see route-guard-flash for the client-side half | | Field-level redaction inside the portal | public-disclosure-projection |
issuable() checks a grant before you mint it, which is the cheaper place to fix all of this.
01Capabilities
Does
- + Role-based access control
- + Client portal
- + Data exposure boundary
Doesn’t
- No exclusions declared
02Requirements & stack
Depends on
No declared dependencies
Credentials needed
None declared
Stack
03Community
No endorsements yetNo verified confirmations yet — be the first.
Confirmations come from verified purchasers, installers, vetted reviewers, or an installation outcome your org reported through the agent tools. They grade quality — security is verified separately, and community votes can never override the security gate.
Sign in to confirm — weight comes from verified usage, not vote count.
Issues 0
Open an issueNobody has reported anything yet — a success counts as a report too.
04Trust Passport
Full passport →0/0 automated components pass. An automated score is never a security guarantee.
- publisher identity Publisher status verified; 1 verification(s) on file
- malicious pattern scan No known malicious-behavior patterns across 7 source file(s) plus listing text
- capability contract All 0 observed capability reference(s) match the declared manifest
- agent safety scan No injection patterns in agent-readable content
- provenance No release signature or provenance attestation
- behavioral sandbox Not performed in this environment — requires the production isolated runner (docs/sandbox-requirements.md). No untrusted code is ever executed on the application host.
Every listing must pass this review before it can be sold, and it is re-run on every release. Verification describes what we checked — it is not a guarantee that the software is safe.
05Versions
Full history →| Version | Channel | Released | Notes |
|---|---|---|---|
| 0.1.0 | stable | Aug 12, 2026 | Initial extraction. |