Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions anonymous-review-identity-escrow/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Anonymous Review Identity Escrow

This is a self-contained module for SCIBASE issue #11, focused on the anonymous identity and privacy edge of User & Project Management.

The module models a privacy-preserving escrow layer for optional anonymous peer review. It gives reviewers deterministic pseudonymous handles, keeps identity-provider evidence redacted from review subjects, evaluates object-level access requests, and supports policy-controlled deanonymization only through an audited break-glass flow.

## What It Covers

- Anonymous reviewer public handles that do not reveal real names.
- Linked identity evidence for ORCID, GitHub, and institutional SAML without exposing raw subjects.
- Identity assurance scoring for MFA, institution verification, verified providers, training, and risk flags.
- Object-level project access decisions for review comments, raw data, and identity exports.
- Deanonymization requests with policy-approved reasons, quorum, due-process notice, and evidence flags.
- Audit hashes for every access decision plus a packet-level digest.

## Demo

Run npm run check, npm test, and npm run demo from this directory.

Expected demo output includes escrow-ready participants, allowed and denied grants, deanonymization approvals, and a deterministic audit digest.

The reviewer-facing visual is in docs/demo.svg; a short demo video is in docs/demo.mp4.

## Files

- src/identity-escrow.js - core deterministic escrow, access, and deanonymization logic.
- data/sample-escrow.json - synthetic sample identities, project objects, access requests, and break-glass cases.
- test/identity-escrow.test.js - Node assert coverage for pseudonyms, redaction, access denial, break-glass controls, and audit hashes.
- scripts/demo.js - terminal demo for reviewers.
- docs/requirement-map.md - maps this module to issue #11 requirements.

## Privacy Notes

No real private identity record, credential, token, ORCID secret, SAML assertion, OAuth key, or external service call is used. All identities and project data are synthetic.
127 changes: 127 additions & 0 deletions anonymous-review-identity-escrow/data/sample-escrow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{
"programId": "blind-review-cohort-q3",
"policy": {
"anonymousMode": true,
"requiredAssurance": 70,
"deanonymizationQuorum": 2,
"allowedDeanonymizationReasons": [
"harassment",
"data-exfiltration",
"research-integrity-investigation"
],
"restrictedScopesForAnonymousReviewers": [
"raw-data-download",
"identity-export",
"billing-admin"
]
},
"participants": [
{
"id": "reviewer-ada",
"displayName": "Ada Chen",
"role": "reviewer",
"profileMode": "anonymous-review",
"linkedIdentities": [
{ "provider": "orcid", "verified": true, "subject": "0000-0002-1825-0097" },
{ "provider": "github", "verified": true, "subject": "ada-lab" },
{ "provider": "saml", "verified": true, "subject": "university.example" }
],
"mfaEnabled": true,
"institutionVerified": true,
"training": {
"humanSubjects": "valid",
"dataUse": "valid"
},
"flags": []
},
{
"id": "reviewer-bo",
"displayName": "Bo Patel",
"role": "reviewer",
"profileMode": "anonymous-review",
"linkedIdentities": [
{ "provider": "orcid", "verified": true, "subject": "0000-0003-1111-2222" },
{ "provider": "github", "verified": false, "subject": "bo-lab" }
],
"mfaEnabled": false,
"institutionVerified": false,
"training": {
"humanSubjects": "valid",
"dataUse": "expired"
},
"flags": ["mfa-missing", "data-use-training-expired"]
},
{
"id": "admin-mira",
"displayName": "Mira Santos",
"role": "admin",
"profileMode": "private",
"linkedIdentities": [
{ "provider": "saml", "verified": true, "subject": "research-office.example" },
{ "provider": "orcid", "verified": true, "subject": "0000-0001-5555-7777" }
],
"mfaEnabled": true,
"institutionVerified": true,
"training": {
"humanSubjects": "valid",
"dataUse": "valid"
},
"flags": []
}
],
"projects": [
{
"id": "project-neuro-crispr",
"visibility": "invitation-only",
"sensitiveScopes": ["raw-data-download", "identity-export"],
"objects": [
{ "id": "manuscript-draft", "kind": "document", "scope": "review-comment" },
{ "id": "supplemental-raw-cells", "kind": "dataset", "scope": "raw-data-download" },
{ "id": "author-roster", "kind": "identity", "scope": "identity-export" }
]
}
],
"accessRequests": [
{
"id": "grant-1",
"participantId": "reviewer-ada",
"projectId": "project-neuro-crispr",
"objectId": "manuscript-draft",
"requestedScope": "review-comment"
},
{
"id": "grant-2",
"participantId": "reviewer-ada",
"projectId": "project-neuro-crispr",
"objectId": "supplemental-raw-cells",
"requestedScope": "raw-data-download"
},
{
"id": "grant-3",
"participantId": "reviewer-bo",
"projectId": "project-neuro-crispr",
"objectId": "manuscript-draft",
"requestedScope": "review-comment"
}
],
"deanonymizationRequests": [
{
"id": "case-1",
"requesterId": "admin-mira",
"targetParticipantId": "reviewer-bo",
"reason": "research-integrity-investigation",
"approvals": ["admin-mira", "ethics-chair"],
"dueProcessNotice": true,
"evidenceFlags": ["data-use-training-expired", "mfa-missing"]
},
{
"id": "case-2",
"requesterId": "admin-mira",
"targetParticipantId": "reviewer-ada",
"reason": "curiosity",
"approvals": ["admin-mira"],
"dueProcessNotice": false,
"evidenceFlags": []
}
]
}
Binary file added anonymous-review-identity-escrow/docs/demo.mp4
Binary file not shown.
26 changes: 26 additions & 0 deletions anonymous-review-identity-escrow/docs/demo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions anonymous-review-identity-escrow/docs/requirement-map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Requirement Map

This module targets SCIBASE-AI/SCIBASE.AI issue #11, "User & Project Management".

| Issue requirement | Implementation evidence |
| --- | --- |
| Optional anonymous user mode for open peer review or public browsing | src/identity-escrow.js issues deterministic pseudonymous handles for profileMode: anonymous-review and hides real display names from review subjects. |
| Account linking across ORCID, GitHub, and institutional identity | data/sample-escrow.json models linked identity providers; scoreIdentityAssurance scores verified providers without exposing subjects. |
| Public vs private profile modes | Escrow records include profileMode and identityVisibleToReviewSubject decisions. |
| Role-based and object-level access control | evaluateAccessRequest decides project/object grants by role, requested scope, assurance score, training, and anonymous-review restrictions. |
| External collaborator and reviewer governance | Access requests model reviewer grants for invitation-only projects and restricted scientific objects. |
| Project-level audit log | Every access and deanonymization decision includes an auditEventHash; the packet includes an overall auditDigest. |
| Meaningful attribution without unsafe identity exposure | Public handles, redacted identity evidence, sealed identity hashes, and break-glass policy separate credit/trust signals from real identity release. |

## Non-goals

- No live OAuth, SAML, ORCID, payment, email, or external API integration.
- No real private identity records are included.
- No credential, secret, or production data is required.
12 changes: 12 additions & 0 deletions anonymous-review-identity-escrow/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "anonymous-review-identity-escrow",
"version": "1.0.0",
"private": true,
"description": "Dependency-free anonymous review identity escrow and access audit module for SCIBASE user/project management.",
"type": "commonjs",
"scripts": {
"check": "node --check src/identity-escrow.js && node --check scripts/demo.js && node --check test/identity-escrow.test.js",
"test": "node test/identity-escrow.test.js",
"demo": "node scripts/demo.js"
}
}
18 changes: 18 additions & 0 deletions anonymous-review-identity-escrow/scripts/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use strict";

const fs = require("node:fs");
const path = require("node:path");
const { createIdentityEscrowPacket } = require("../src/identity-escrow");

const fixture = JSON.parse(
fs.readFileSync(path.join(__dirname, "../data/sample-escrow.json"), "utf8")
);
const packet = createIdentityEscrowPacket(fixture);

console.log("Program: " + packet.programId);
console.log("Escrow-ready participants: " + packet.summary.escrowReady + "/" + packet.summary.participants);
console.log("Allowed access grants: " + packet.summary.allowedAccess);
console.log("Denied access grants: " + packet.summary.deniedAccess);
console.log("Deanonymization approved: " + packet.summary.deanonymizationApproved);
console.log("Top action: " + packet.actions[0].message);
console.log("Audit digest: " + packet.auditDigest);
Loading