From 6627c560c9f87c3dae181d9764224444ecf32c6a Mon Sep 17 00:00:00 2001 From: HunterCML <5335527+HunterCML@users.noreply.github.com> Date: Sat, 23 May 2026 10:02:14 -0500 Subject: [PATCH] Add project provisioning baseline guard --- project-provisioning-baseline-guard/README.md | 19 + .../acceptance-notes.md | 21 + project-provisioning-baseline-guard/demo.js | 171 +++++++ project-provisioning-baseline-guard/demo.mp4 | Bin 0 -> 99909 bytes project-provisioning-baseline-guard/demo.svg | 27 + project-provisioning-baseline-guard/index.js | 484 ++++++++++++++++++ .../render-video.js | 151 ++++++ .../reports/provisioning-baseline-packet.json | 26 + .../reports/provisioning-baseline-report.md | 21 + .../reports/summary.svg | 27 + .../requirements-map.md | 17 + project-provisioning-baseline-guard/test.js | 197 +++++++ 12 files changed, 1161 insertions(+) create mode 100644 project-provisioning-baseline-guard/README.md create mode 100644 project-provisioning-baseline-guard/acceptance-notes.md create mode 100644 project-provisioning-baseline-guard/demo.js create mode 100644 project-provisioning-baseline-guard/demo.mp4 create mode 100644 project-provisioning-baseline-guard/demo.svg create mode 100644 project-provisioning-baseline-guard/index.js create mode 100644 project-provisioning-baseline-guard/render-video.js create mode 100644 project-provisioning-baseline-guard/reports/provisioning-baseline-packet.json create mode 100644 project-provisioning-baseline-guard/reports/provisioning-baseline-report.md create mode 100644 project-provisioning-baseline-guard/reports/summary.svg create mode 100644 project-provisioning-baseline-guard/requirements-map.md create mode 100644 project-provisioning-baseline-guard/test.js diff --git a/project-provisioning-baseline-guard/README.md b/project-provisioning-baseline-guard/README.md new file mode 100644 index 00000000..1f399367 --- /dev/null +++ b/project-provisioning-baseline-guard/README.md @@ -0,0 +1,19 @@ +# Project Provisioning Baseline Guard + +This module adds a focused User & Project Management guard for creating new research workspaces safely. + +It evaluates whether a project can be provisioned by checking requester authority, verified institution/profile evidence, fresh MFA, required launch metadata, template controls, visibility rules by data classification, initial project roles, object-level grants, external collaborator constraints, and immutable audit evidence. + +## Run + +```sh +node project-provisioning-baseline-guard/test.js +node project-provisioning-baseline-guard/demo.js +node project-provisioning-baseline-guard/render-video.js +``` + +The demo writes JSON, Markdown, and SVG reviewer artifacts to `project-provisioning-baseline-guard/reports/`. + +## Review Surface + +The implementation is dependency-free, uses synthetic data only, and does not call external APIs or read credentials. diff --git a/project-provisioning-baseline-guard/acceptance-notes.md b/project-provisioning-baseline-guard/acceptance-notes.md new file mode 100644 index 00000000..db2e2385 --- /dev/null +++ b/project-provisioning-baseline-guard/acceptance-notes.md @@ -0,0 +1,21 @@ +# Acceptance Notes + +## Validation + +- `node project-provisioning-baseline-guard/test.js` +- `node project-provisioning-baseline-guard/demo.js` +- `node project-provisioning-baseline-guard/render-video.js` +- `node --check project-provisioning-baseline-guard/index.js` +- `node --check project-provisioning-baseline-guard/test.js` +- `node --check project-provisioning-baseline-guard/demo.js` +- `node --check project-provisioning-baseline-guard/render-video.js` +- `ffprobe -v error -show_entries format=duration,size -show_entries stream=codec_name,width,height -of default=noprint_wrappers=1 project-provisioning-baseline-guard/demo.mp4` + +## Acceptance Coverage + +- A controlled institutional project with fresh requester MFA, verified affiliation, required metadata, template controls, owner and data-steward roles, scoped external collaboration, and audit events can provision cleanly. +- Restricted human-subject projects cannot start with public visibility. +- Missing requester authority and stale MFA block provisioning. +- External restricted-data grants require data-use agreement evidence. +- Missing template controls block workspace creation. +- The output audit digest is deterministic for replay and reviewer comparison. diff --git a/project-provisioning-baseline-guard/demo.js b/project-provisioning-baseline-guard/demo.js new file mode 100644 index 00000000..f6b5b27a --- /dev/null +++ b/project-provisioning-baseline-guard/demo.js @@ -0,0 +1,171 @@ +const fs = require("fs"); +const path = require("path"); +const { evaluateProjectProvisioning } = require("./index"); + +const outputDir = path.join(__dirname, "reports"); +fs.mkdirSync(outputDir, { recursive: true }); + +function packetForDemo() { + return { + now: "2026-06-01T12:00:00Z", + policy: { + maxMfaAgeHours: 12, + requiredMetadataFields: ["projectName", "projectPurpose", "discipline", "institutionId", "dataClassification"], + requiredProjectRoles: ["owner"], + allowedExternalDomains: ["partner-lab.org"], + visibilityByClassification: { + open: ["public", "institutional", "private"], + controlled: ["institutional", "private"], + "restricted-human-subjects": ["private"], + }, + templates: { + "controlled-study": { + id: "controlled-study", + allowedClassifications: ["controlled", "restricted-human-subjects"], + requiredMetadataFields: ["retentionPlan"], + requiredProjectRoles: ["data-steward"], + requiredControls: ["auditTrail", "objectGrantReview"], + }, + }, + }, + users: [ + { + id: "user-pi-ada", + type: "internal", + projectCreator: true, + email: "ada@northbridge.edu", + mfaAt: "2026-06-01T08:00:00Z", + verifiedAffiliations: [{ institutionId: "northbridge", status: "verified" }], + identifiers: [{ type: "orcid", value: "0000-0002-1825-0097", status: "verified" }], + }, + { + id: "user-steward-lin", + type: "internal", + email: "lin@northbridge.edu", + verifiedAffiliations: [{ institutionId: "northbridge", status: "verified" }], + identifiers: [{ type: "orcid", value: "0000-0001-5555-1212", status: "verified" }], + }, + { + id: "user-ext-ren", + type: "external", + email: "ren@partner-lab.org", + training: { restrictedData: "current" }, + verifiedAffiliations: [{ institutionId: "partner-lab", status: "verified" }], + identifiers: [{ type: "orcid", value: "0000-0003-9999-8888", status: "verified" }], + }, + ], + request: { + requestId: "provision-1", + projectId: "project-neuro-qc", + name: "Neuro QC Consortium", + requesterId: "user-pi-ada", + institutionId: "northbridge", + templateId: "controlled-study", + dataClassification: "controlled", + visibility: "institutional", + metadata: { + projectName: "Neuro QC Consortium", + projectPurpose: "Coordinate reproducible quality-control notebooks for multi-site neuroimaging studies.", + discipline: "neuroscience", + institutionId: "northbridge", + dataClassification: "controlled", + retentionPlan: "retain-seven-years", + }, + controls: { auditTrail: true, objectGrantReview: true }, + roleAssignments: [ + { userId: "user-pi-ada", role: "owner", scope: "project" }, + { userId: "user-steward-lin", role: "data-steward", scope: "project" }, + { userId: "user-ext-ren", role: "viewer", scope: "project" }, + ], + objectGrants: [ + { principalId: "user-pi-ada", objectType: "workspace", permissions: ["admin"] }, + { principalId: "user-steward-lin", objectType: "controlled-dataset", permissions: ["read", "review"] }, + { principalId: "user-ext-ren", objectType: "manuscript", permissions: ["read"] }, + ], + externalCollaborators: ["user-ext-ren"], + approvals: [{ type: "sponsor-review", status: "approved", subjectId: "project-neuro-qc" }], + auditEvents: [ + { type: "provision-requested", actorId: "user-pi-ada", at: "2026-06-01T08:03:00Z" }, + { type: "baseline-evaluated", actorId: "system", at: "2026-06-01T08:04:00Z" }, + ], + }, + }; +} + +function markdownReport(report) { + return [ + "# Project Provisioning Baseline Guard Demo", + "", + `Decision: ${report.decision}`, + `Audit digest: ${report.auditDigest}`, + "", + "## Public Summary", + "", + `- Project: ${report.publicSummary.projectName} (${report.projectId})`, + `- Template: ${report.publicSummary.templateId}`, + `- Visibility: ${report.publicSummary.visibility}`, + `- Data classification: ${report.publicSummary.dataClassification}`, + "", + "## Finding Counts", + "", + `- Blockers: ${report.counts.blocker}`, + `- Warnings: ${report.counts.warning}`, + `- Info: ${report.counts.info}`, + "", + "## Action Queue", + "", + ...(report.actionQueue.length + ? report.actionQueue.map((action) => `- ${action.severity} ${action.code} (${action.subject}): ${action.remediation}`) + : ["- No remediation actions required."]), + "", + ].join("\n"); +} + +function svgReport(report) { + const blocked = report.counts.blocker; + const warnings = report.counts.warning; + const readyColor = report.decision === "provision-ready" ? "#68d391" : "#f6ad55"; + + return ` + Project Provisioning Baseline Guard Demo + A user and project management demo showing project launch controls, identity evidence, visibility rules, role grants, and audit evidence. + + + SCIBASE bounty demo artifact + Project Provisioning Baseline Guard + Issue #11: user and project management launch governance + + + PROVISIONING BASELINE + 1. Verify requester authority and MFA + 2. Check metadata and template controls + 3. Enforce visibility by data classification + 4. Validate initial roles and object grants + 5. Emit audit digest and action queue + $ node project-provisioning-baseline-guard/test.js + decision: ${report.decision} + blockers: ${blocked} | warnings: ${warnings} + Reviewer artifacts + reports/provisioning-baseline-packet.json + reports/provisioning-baseline-report.md + + + + Synthetic project launch packet + deterministic audit evidence + +`; +} + +const report = evaluateProjectProvisioning(packetForDemo()); +const jsonPath = path.join(outputDir, "provisioning-baseline-packet.json"); +const markdownPath = path.join(outputDir, "provisioning-baseline-report.md"); +const svgPath = path.join(outputDir, "summary.svg"); + +fs.writeFileSync(jsonPath, JSON.stringify(report, null, 2)); +fs.writeFileSync(markdownPath, markdownReport(report)); +fs.writeFileSync(svgPath, svgReport(report)); + +console.log(`Wrote ${jsonPath}`); +console.log(`Wrote ${markdownPath}`); +console.log(`Wrote ${svgPath}`); +console.log(`${report.decision}: ${report.counts.blocker} blocker(s), ${report.counts.warning} warning(s), ${report.auditDigest}`); diff --git a/project-provisioning-baseline-guard/demo.mp4 b/project-provisioning-baseline-guard/demo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..39fd8b1e2be3f33699ad065d99b5cc3b1717d056 GIT binary patch literal 99909 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 literal 0 HcmV?d00001 diff --git a/project-provisioning-baseline-guard/demo.svg b/project-provisioning-baseline-guard/demo.svg new file mode 100644 index 00000000..15ce3242 --- /dev/null +++ b/project-provisioning-baseline-guard/demo.svg @@ -0,0 +1,27 @@ + + Project Provisioning Baseline Guard Demo + A user and project management demo showing project launch controls, identity evidence, visibility rules, role grants, and audit evidence. + + + SCIBASE bounty demo artifact + Project Provisioning Baseline Guard + Issue #11: user and project management launch governance + + + PROVISIONING BASELINE + 1. Verify requester authority and MFA + 2. Check metadata and template controls + 3. Enforce visibility by data classification + 4. Validate initial roles and object grants + 5. Emit audit digest and action queue + $ node project-provisioning-baseline-guard/test.js + tests passed: identity, metadata, visibility, + roles, external grants, deterministic digest + Reviewer artifacts + reports/provisioning-baseline-packet.json + reports/provisioning-baseline-report.md + + + + Committed video demo + focused tests + synthetic evidence + diff --git a/project-provisioning-baseline-guard/index.js b/project-provisioning-baseline-guard/index.js new file mode 100644 index 00000000..e1328286 --- /dev/null +++ b/project-provisioning-baseline-guard/index.js @@ -0,0 +1,484 @@ +const crypto = require("crypto"); + +const HOUR_MS = 60 * 60 * 1000; + +function asArray(value) { + if (!value) return []; + return Array.isArray(value) ? value : [value]; +} + +function normalize(value) { + return String(value || "").trim().toLowerCase(); +} + +function unique(values) { + return [...new Set(asArray(values).map(normalize).filter(Boolean))]; +} + +function uniqueFields(values) { + const seen = new Set(); + const fields = []; + for (const value of asArray(values).filter(Boolean)) { + const key = normalize(value); + if (seen.has(key)) continue; + seen.add(key); + fields.push(value); + } + return fields; +} + +function stableStringify(value) { + if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`; + if (value && typeof value === "object") { + return `{${Object.keys(value) + .sort() + .map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`) + .join(",")}}`; + } + return JSON.stringify(value); +} + +function digest(value) { + return crypto.createHash("sha256").update(stableStringify(value)).digest("hex"); +} + +function parseDate(value) { + const time = Date.parse(value || ""); + return Number.isNaN(time) ? 0 : time; +} + +function hoursSince(value, now) { + const time = parseDate(value); + if (!time || !now) return Infinity; + return Math.floor((now - time) / HOUR_MS); +} + +function addFinding(findings, severity, code, subject, message, remediation) { + findings.push({ severity, code, subject, message, remediation }); +} + +function byId(records) { + return asArray(records).reduce((acc, record) => { + if (record && record.id) acc[record.id] = record; + return acc; + }, {}); +} + +function hasVerifiedAffiliation(user, institutionId) { + const target = normalize(institutionId); + return asArray(user.verifiedAffiliations).some((affiliation) => { + if (normalize(affiliation.institutionId || affiliation.id) !== target) return false; + return normalize(affiliation.status || "verified") === "verified"; + }); +} + +function hasVerifiedIdentifier(user, type) { + return asArray(user.identifiers).some( + (identifier) => normalize(identifier.type) === normalize(type) && normalize(identifier.status || "verified") === "verified", + ); +} + +function roleAssignmentsFor(assignments, userId) { + const target = normalize(userId); + return asArray(assignments).filter((assignment) => normalize(assignment.userId) === target); +} + +function hasAnyProjectRole(assignments, roles) { + const wanted = unique(roles); + return asArray(assignments).some((assignment) => wanted.includes(normalize(assignment.role))); +} + +function approvalExists(approvals, type, subjectId) { + const targetType = normalize(type); + const targetSubject = normalize(subjectId); + return asArray(approvals).some((approval) => { + if (normalize(approval.type) !== targetType) return false; + if (targetSubject && normalize(approval.subjectId || approval.userId || approval.projectId) !== targetSubject) return false; + return normalize(approval.status || "approved") === "approved"; + }); +} + +function expectedMetadataFields(policy, request, template) { + const required = [ + ...asArray(policy.requiredMetadataFields), + ...asArray(template.requiredMetadataFields), + ]; + + if (normalize(request.dataClassification).includes("restricted")) { + required.push("irbProtocolId", "dataUseAgreementId", "retentionPlan"); + } + + return uniqueFields(required); +} + +function readField(record, field) { + const target = normalize(field); + for (const [key, value] of Object.entries(record || {})) { + if (normalize(key) === target) return value; + } + return undefined; +} + +function visibilityAllowed(policy, request) { + const classification = normalize(request.dataClassification); + const visibility = normalize(request.visibility); + const allowedByClass = policy.visibilityByClassification || {}; + const allowed = unique(allowedByClass[classification] || policy.allowedVisibilities || []); + + if (allowed.length === 0) return true; + return allowed.includes(visibility); +} + +function grantTouchesRestrictedData(grant) { + const objectType = normalize(grant.objectType || grant.resourceType); + const permissions = unique(grant.permissions || grant.permission); + return objectType.includes("restricted") || objectType.includes("human-subject") || permissions.some((permission) => ["download", "export", "share"].includes(permission)); +} + +function publicProvisioningSummary(request, decision, counts) { + return { + projectId: request.projectId, + projectName: request.name, + templateId: request.templateId, + visibility: request.visibility, + dataClassification: request.dataClassification, + decision, + findingCounts: counts, + }; +} + +function evaluateRequester(request, usersById, policy, findings, now) { + const requester = usersById[request.requesterId] || {}; + const requesterAssignments = roleAssignmentsFor(request.roleAssignments, request.requesterId); + const authorityRoles = policy.creatorRoles || ["principal-investigator", "project-admin", "institution-admin"]; + const maxMfaAgeHours = Number(policy.maxMfaAgeHours || 24); + + if (!requester.id) { + addFinding( + findings, + "blocker", + "REQUESTER_PROFILE_MISSING", + request.requesterId || "requester", + "Project provisioning requires a resolvable requester profile.", + "Load the requester profile before creating the workspace.", + ); + return; + } + + if (!requester.projectCreator && !hasAnyProjectRole(requesterAssignments, authorityRoles)) { + addFinding( + findings, + "blocker", + "REQUESTER_AUTHORITY_MISSING", + requester.id, + "Requester lacks a creator flag or approved project creation role.", + "Require a principal investigator, project admin, institution admin, or explicit projectCreator grant.", + ); + } + + if (!hasVerifiedAffiliation(requester, request.institutionId)) { + addFinding( + findings, + "blocker", + "REQUESTER_AFFILIATION_UNVERIFIED", + requester.id, + "Requester does not have a verified affiliation for the target institution.", + "Verify institutional SAML, domain, or administrator evidence before provisioning.", + ); + } + + if (!hasVerifiedIdentifier(requester, "orcid")) { + addFinding( + findings, + "warning", + "REQUESTER_ORCID_UNVERIFIED", + requester.id, + "Requester profile lacks a verified ORCID identifier.", + "Allow steward review or require ORCID linkage before public researcher profile exposure.", + ); + } + + if (hoursSince(requester.mfaAt, now) > maxMfaAgeHours) { + addFinding( + findings, + "blocker", + "REQUESTER_MFA_STALE", + requester.id, + `Requester MFA is older than ${maxMfaAgeHours} hour(s).`, + "Require a fresh MFA challenge before opening the project space.", + ); + } +} + +function evaluateMetadata(request, policy, template, findings) { + const metadata = request.metadata || {}; + for (const field of expectedMetadataFields(policy, request, template)) { + const value = readField(metadata, field) || readField(request, field); + if (!value) { + addFinding( + findings, + "blocker", + "REQUIRED_METADATA_MISSING", + field, + `Required project provisioning metadata is missing: ${field}.`, + "Collect the missing metadata before the workspace is created.", + ); + } + } + + const projectName = String(request.name || metadata.projectName || ""); + if (projectName.trim().length < Number(policy.minimumProjectNameLength || 6)) { + addFinding( + findings, + "warning", + "PROJECT_NAME_TOO_SHORT", + request.projectId || "project", + "Project name is too short for reviewer and audit records.", + "Require a descriptive title before showing the workspace in project lists.", + ); + } +} + +function evaluateVisibility(request, policy, findings) { + if (!visibilityAllowed(policy, request)) { + addFinding( + findings, + "blocker", + "VISIBILITY_CLASSIFICATION_CONFLICT", + request.visibility, + `Visibility ${request.visibility} is not allowed for ${request.dataClassification} projects.`, + "Lower visibility or reclassify the project before provisioning.", + ); + } + + if (normalize(request.visibility) === "public" && asArray(request.externalCollaborators).length > 0) { + addFinding( + findings, + "info", + "PUBLIC_PROJECT_EXTERNAL_COLLABORATORS", + request.projectId || "project", + "Public project includes external collaborators at creation time.", + "Keep object-level grants narrow and retain collaborator audit evidence.", + ); + } +} + +function evaluateTemplate(request, policy, findings) { + const template = (policy.templates || {})[request.templateId] || {}; + if (!template.id && request.templateId) { + addFinding( + findings, + "warning", + "UNKNOWN_TEMPLATE_ID", + request.templateId, + "Project references a template that is not registered in the provisioning policy.", + "Route to steward review or register the template baseline before launch.", + ); + } + + const allowedClassifications = unique(template.allowedClassifications); + if (allowedClassifications.length > 0 && !allowedClassifications.includes(normalize(request.dataClassification))) { + addFinding( + findings, + "blocker", + "TEMPLATE_CLASSIFICATION_MISMATCH", + request.templateId, + "Selected project template is not approved for this data classification.", + "Choose an approved template or add steward approval for the classification.", + ); + } + + for (const control of asArray(template.requiredControls)) { + if (!request.controls || request.controls[control] !== true) { + addFinding( + findings, + "blocker", + "TEMPLATE_CONTROL_MISSING", + control, + `Template control ${control} has not been enabled.`, + "Enable the required template control before creating the workspace.", + ); + } + } + + return template; +} + +function evaluateInitialRoles(request, policy, template, usersById, findings) { + const roleAssignments = asArray(request.roleAssignments); + const requiredRoles = unique([...(policy.requiredProjectRoles || ["owner"]), ...asArray(template.requiredProjectRoles)]); + + for (const role of requiredRoles) { + if (!hasAnyProjectRole(roleAssignments, [role])) { + addFinding( + findings, + "blocker", + "REQUIRED_PROJECT_ROLE_MISSING", + role, + `Project is missing required initial role: ${role}.`, + "Add the required role assignment before provisioning.", + ); + } + } + + for (const assignment of roleAssignments) { + const user = usersById[assignment.userId] || {}; + if (!user.id) { + addFinding( + findings, + "blocker", + "ROLE_ASSIGNEE_MISSING", + assignment.userId || "unknown", + "Initial role assignment references a missing user profile.", + "Resolve every role assignee before committing the role matrix.", + ); + continue; + } + + if (normalize(user.type) === "external" && ["owner", "project-admin", "data-steward"].includes(normalize(assignment.role))) { + addFinding( + findings, + "blocker", + "EXTERNAL_COLLABORATOR_PRIVILEGED_ROLE", + user.id, + "External collaborator is assigned a privileged launch role.", + "Use a viewer, contributor, or scoped collaborator role until sponsor approval is recorded.", + ); + } + } +} + +function evaluateExternalCollaborators(request, policy, usersById, findings) { + const approvals = asArray(request.approvals); + const objectGrants = asArray(request.objectGrants); + const allowedDomains = unique(policy.allowedExternalDomains); + + for (const collaboratorRef of asArray(request.externalCollaborators)) { + const collaboratorId = typeof collaboratorRef === "string" ? collaboratorRef : collaboratorRef.userId || collaboratorRef.id; + const collaborator = usersById[collaboratorId] || {}; + if (!collaborator.id) { + addFinding( + findings, + "blocker", + "EXTERNAL_COLLABORATOR_PROFILE_MISSING", + collaboratorId, + "External collaborator profile is missing.", + "Invite or verify the collaborator profile before provisioning.", + ); + continue; + } + + const emailDomain = normalize(collaborator.email || "").split("@")[1] || normalize(collaborator.domain); + if (allowedDomains.length > 0 && !allowedDomains.includes(emailDomain)) { + addFinding( + findings, + "warning", + "EXTERNAL_DOMAIN_NOT_ALLOWLISTED", + collaborator.id, + `External collaborator domain ${emailDomain || "unknown"} is not allowlisted.`, + "Require sponsor review before retaining this collaborator at project launch.", + ); + } + + const restrictedGrant = objectGrants.some( + (grant) => normalize(grant.principalId || grant.userId) === normalize(collaborator.id) && grantTouchesRestrictedData(grant), + ); + if (restrictedGrant && !approvalExists(approvals, "data-use-agreement", collaborator.id)) { + addFinding( + findings, + "blocker", + "EXTERNAL_RESTRICTED_DATA_APPROVAL_MISSING", + collaborator.id, + "External collaborator has a restricted data grant without data-use agreement approval.", + "Add data-use agreement evidence or remove the restricted grant.", + ); + } + + const hasCurrentRestrictedTraining = collaborator.training && normalize(collaborator.training.restrictedData) === "current"; + if (restrictedGrant && !hasCurrentRestrictedTraining) { + addFinding( + findings, + "warning", + "EXTERNAL_RESTRICTED_DATA_TRAINING_GAP", + collaborator.id, + "External collaborator restricted-data training is missing or stale.", + "Require current training evidence before enabling restricted data access.", + ); + } + } +} + +function evaluateAuditEvidence(request, findings) { + const eventTypes = unique(asArray(request.auditEvents).map((event) => event.type)); + for (const expected of ["provision-requested", "baseline-evaluated"]) { + if (!eventTypes.includes(expected)) { + addFinding( + findings, + "warning", + "AUDIT_EVENT_MISSING", + expected, + `Audit event ${expected} is missing from the provisioning packet.`, + "Record immutable launch evidence before approving the workspace.", + ); + } + } +} + +function findingCounts(findings) { + return findings.reduce( + (acc, finding) => { + acc[finding.severity] = (acc[finding.severity] || 0) + 1; + return acc; + }, + { blocker: 0, warning: 0, info: 0 }, + ); +} + +function evaluateProjectProvisioning(packet = {}) { + const policy = packet.policy || {}; + const request = packet.request || {}; + const usersById = byId(packet.users); + const now = parseDate(packet.now || new Date().toISOString()); + const findings = []; + const template = evaluateTemplate(request, policy, findings); + + evaluateRequester(request, usersById, policy, findings, now); + evaluateMetadata(request, policy, template, findings); + evaluateVisibility(request, policy, findings); + evaluateInitialRoles(request, policy, template, usersById, findings); + evaluateExternalCollaborators(request, policy, usersById, findings); + evaluateAuditEvidence(request, findings); + + const counts = findingCounts(findings); + const decision = + counts.blocker > 0 + ? "hold-provisioning" + : counts.warning > 0 + ? "provision-with-steward-review" + : "provision-ready"; + const actionQueue = findings.map((finding) => ({ + severity: finding.severity, + code: finding.code, + subject: finding.subject, + remediation: finding.remediation, + })); + const result = { + generatedAt: packet.now || new Date().toISOString(), + decision, + projectId: request.projectId, + counts, + findings, + actionQueue, + publicSummary: publicProvisioningSummary(request, decision, counts), + }; + + return { + ...result, + auditDigest: digest(result), + }; +} + +module.exports = { + evaluateProjectProvisioning, + stableStringify, +}; diff --git a/project-provisioning-baseline-guard/render-video.js b/project-provisioning-baseline-guard/render-video.js new file mode 100644 index 00000000..824091d8 --- /dev/null +++ b/project-provisioning-baseline-guard/render-video.js @@ -0,0 +1,151 @@ +const childProcess = require("child_process"); +const fs = require("fs"); +const path = require("path"); + +const frames = [ + ["Problem", "New research workspaces can start with weak requester evidence, unsafe visibility, missing metadata, and overbroad initial grants."], + ["Implementation", "The guard validates identity posture, template controls, metadata, visibility policy, initial roles, object grants, and audit events."], + ["Acceptance", "Unsafe launch packets are held when restricted data, external collaborators, missing controls, or stale MFA create project risk."], + ["Demo output", "decision: provision-ready | blockers: 0 | actionQueue: empty | auditDigest: deterministic"], +]; + +function ffmpegCandidates() { + const localAppData = process.env.LOCALAPPDATA; + const candidates = [process.env.FFMPEG_PATH, "ffmpeg.exe", "ffmpeg"].filter(Boolean); + + if (localAppData) { + candidates.unshift( + path.join( + localAppData, + "Microsoft", + "WinGet", + "Packages", + "Gyan.FFmpeg.Essentials_Microsoft.Winget.Source_8wekyb3d8bbwe", + "ffmpeg-8.1.1-essentials_build", + "bin", + "ffmpeg.exe", + ), + ); + } + + return candidates; +} + +function findFfmpeg() { + for (const candidate of ffmpegCandidates()) { + if (candidate.includes(path.sep) && fs.existsSync(candidate)) return candidate; + try { + childProcess.execFileSync(candidate, ["-version"], { stdio: "ignore" }); + return candidate; + } catch { + // Try the next candidate. + } + } + + throw new Error("FFmpeg was not found. Install it or set FFMPEG_PATH."); +} + +function quoteText(text) { + return String(text) + .replace(/\\/g, "\\\\") + .replace(/:/g, "\\:") + .replace(/'/g, "\\'") + .replace(/%/g, "\\%"); +} + +function drawText(text, x, y, size, color, weight = "") { + const style = weight ? `:font=${weight}` : ""; + return `drawtext=text='${quoteText(text)}'${style}:x=${x}:y=${y}:fontsize=${size}:fontcolor=${color}`; +} + +function wrapText(text, maxChars) { + const words = String(text).split(/\s+/); + const lines = []; + let line = ""; + + for (const word of words) { + const next = line ? `${line} ${word}` : word; + if (next.length > maxChars && line) { + lines.push(line); + line = word; + } else { + line = next; + } + } + + if (line) lines.push(line); + return lines; +} + +function textBlock(text, x, y, size, color, maxChars, lineHeight) { + return wrapText(text, maxChars).map((line, index) => drawText(line, x, y + index * lineHeight, size, color)); +} + +function slideFilter(frame, slideIndex, inputLabel) { + const filters = []; + const label = frame[0].toUpperCase(); + const body = frame[1]; + + filters.push("drawbox=x=0:y=0:w=iw:h=ih:color=0d1726@1:t=fill"); + filters.push("drawbox=x=0:y=0:w=iw:h=130:color=10243a@1:t=fill"); + filters.push("drawbox=x=64:y=214:w=540:h=318:color=ffffff@0.93:t=fill"); + filters.push("drawbox=x=676:y=214:w=540:h=318:color=07101c@0.84:t=fill"); + filters.push(drawText("SCIBASE bounty demo artifact", 64, 44, 22, "d8e8f7")); + filters.push(drawText("Project Provisioning Baseline Guard", 64, 92, 42, "ffffff")); + filters.push(drawText("Issue #11: user and project management", 66, 150, 24, "b8cbe1")); + filters.push(drawText(label, 96, 250, 18, "16405f")); + filters.push(...textBlock(body, 96, 302, 23, "152036", 34, 34)); + filters.push(drawText("$ node project-provisioning-baseline-guard/test.js", 708, 254, 18, "68d391")); + filters.push(...textBlock("tests passed: requester evidence, metadata, visibility, external grants, template controls, deterministic digest", 708, 304, 19, "e9f7ef", 40, 28)); + filters.push(drawText("Validation path", 708, 404, 18, "a8bdd1")); + filters.push(drawText("1. Focused tests", 708, 438, 21, "ffffff")); + filters.push(drawText("2. Demo JSON and Markdown", 708, 468, 21, "ffffff")); + filters.push(drawText("3. Requirement map and acceptance notes", 708, 498, 21, "ffffff")); + + for (let index = 0; index < frames.length; index += 1) { + const color = index === slideIndex ? "68d391@1" : "ffffff@0.30"; + filters.push(`drawbox=x=${64 + index * 54}:y=590:w=38:h=8:color=${color}:t=fill`); + } + + filters.push(drawText("Committed video demo + focused tests + synthetic evidence", 64, 650, 21, "d8e8f7")); + filters.push(drawText(`Slide ${slideIndex + 1} / ${frames.length}`, 1096, 650, 18, "b8cbe1")); + + return `${inputLabel}${filters.join(",")}[v${slideIndex}]`; +} + +function renderDemo(ffmpeg, outputPath) { + const args = ["-y"]; + const slideDuration = "2.1"; + + for (let index = 0; index < frames.length; index += 1) { + args.push("-f", "lavfi", "-t", slideDuration, "-i", "color=c=0d1726:s=1280x720:r=30"); + } + + const slideFilters = frames.map((frame, index) => slideFilter(frame, index, `[${index}:v]`)); + const concatInputs = frames.map((_, index) => `[v${index}]`).join(""); + const filterComplex = `${slideFilters.join(";")};${concatInputs}concat=n=${frames.length}:v=1:a=0[outv]`; + + args.push( + "-filter_complex", + filterComplex, + "-map", + "[outv]", + "-c:v", + "libx264", + "-preset", + "veryfast", + "-crf", + "23", + "-pix_fmt", + "yuv420p", + "-movflags", + "+faststart", + outputPath, + ); + + childProcess.execFileSync(ffmpeg, args, { stdio: "inherit" }); +} + +const outputPath = path.join(__dirname, "demo.mp4"); +renderDemo(findFfmpeg(), outputPath); +console.log(`Wrote ${outputPath} (${fs.statSync(outputPath).size} bytes)`); diff --git a/project-provisioning-baseline-guard/reports/provisioning-baseline-packet.json b/project-provisioning-baseline-guard/reports/provisioning-baseline-packet.json new file mode 100644 index 00000000..71a72be0 --- /dev/null +++ b/project-provisioning-baseline-guard/reports/provisioning-baseline-packet.json @@ -0,0 +1,26 @@ +{ + "generatedAt": "2026-06-01T12:00:00Z", + "decision": "provision-ready", + "projectId": "project-neuro-qc", + "counts": { + "blocker": 0, + "warning": 0, + "info": 0 + }, + "findings": [], + "actionQueue": [], + "publicSummary": { + "projectId": "project-neuro-qc", + "projectName": "Neuro QC Consortium", + "templateId": "controlled-study", + "visibility": "institutional", + "dataClassification": "controlled", + "decision": "provision-ready", + "findingCounts": { + "blocker": 0, + "warning": 0, + "info": 0 + } + }, + "auditDigest": "4d892fa7ef881f2261ac7b2c22774bc59439d85b74ed1a3688af60be7c04b083" +} \ No newline at end of file diff --git a/project-provisioning-baseline-guard/reports/provisioning-baseline-report.md b/project-provisioning-baseline-guard/reports/provisioning-baseline-report.md new file mode 100644 index 00000000..169d2262 --- /dev/null +++ b/project-provisioning-baseline-guard/reports/provisioning-baseline-report.md @@ -0,0 +1,21 @@ +# Project Provisioning Baseline Guard Demo + +Decision: provision-ready +Audit digest: 4d892fa7ef881f2261ac7b2c22774bc59439d85b74ed1a3688af60be7c04b083 + +## Public Summary + +- Project: Neuro QC Consortium (project-neuro-qc) +- Template: controlled-study +- Visibility: institutional +- Data classification: controlled + +## Finding Counts + +- Blockers: 0 +- Warnings: 0 +- Info: 0 + +## Action Queue + +- No remediation actions required. diff --git a/project-provisioning-baseline-guard/reports/summary.svg b/project-provisioning-baseline-guard/reports/summary.svg new file mode 100644 index 00000000..b37ea547 --- /dev/null +++ b/project-provisioning-baseline-guard/reports/summary.svg @@ -0,0 +1,27 @@ + + Project Provisioning Baseline Guard Demo + A user and project management demo showing project launch controls, identity evidence, visibility rules, role grants, and audit evidence. + + + SCIBASE bounty demo artifact + Project Provisioning Baseline Guard + Issue #11: user and project management launch governance + + + PROVISIONING BASELINE + 1. Verify requester authority and MFA + 2. Check metadata and template controls + 3. Enforce visibility by data classification + 4. Validate initial roles and object grants + 5. Emit audit digest and action queue + $ node project-provisioning-baseline-guard/test.js + decision: provision-ready + blockers: 0 | warnings: 0 + Reviewer artifacts + reports/provisioning-baseline-packet.json + reports/provisioning-baseline-report.md + + + + Synthetic project launch packet + deterministic audit evidence + diff --git a/project-provisioning-baseline-guard/requirements-map.md b/project-provisioning-baseline-guard/requirements-map.md new file mode 100644 index 00000000..cb44ca6c --- /dev/null +++ b/project-provisioning-baseline-guard/requirements-map.md @@ -0,0 +1,17 @@ +# Requirements Map + +Issue #11 asks for User & Project Management features, including secure authentication, user profiles, project workspaces, role-based access, collaboration, and audit trails. + +This submission focuses on a distinct project provisioning baseline lane: + +- Verifies that the project requester has creation authority, institutional affiliation evidence, ORCID linkage, and fresh MFA. +- Checks required project metadata before a new workspace appears in user project lists. +- Enforces visibility constraints by data classification so restricted projects cannot start public. +- Validates registered project templates and their required launch controls. +- Requires owner and data-steward role coverage for controlled research projects. +- Blocks privileged launch roles for external collaborators. +- Requires data-use agreement evidence before external collaborators can receive restricted data export grants. +- Preserves immutable provisioning audit events and emits deterministic audit digests. +- Produces public reviewer summaries without exposing private collaborator evidence. + +The scope intentionally avoids the existing broad RBAC/workspace ledger, privacy access review, member lifecycle/offboarding, institutional recertification, anonymous-review escrow, identity merge/export, data-room consent, researcher profile sync, archive handoff, access-audit anomaly, role delegation, invitation-domain/MFA, funding-attribution, service-token governance, deletion/erasure, break-glass, and visibility-transition submissions. diff --git a/project-provisioning-baseline-guard/test.js b/project-provisioning-baseline-guard/test.js new file mode 100644 index 00000000..79b85adc --- /dev/null +++ b/project-provisioning-baseline-guard/test.js @@ -0,0 +1,197 @@ +const assert = require("assert"); +const { evaluateProjectProvisioning } = require("./index"); + +function basePacket(overrides = {}) { + const packet = { + now: "2026-06-01T12:00:00Z", + policy: { + maxMfaAgeHours: 12, + minimumProjectNameLength: 6, + requiredMetadataFields: ["projectName", "projectPurpose", "discipline", "institutionId", "dataClassification"], + requiredProjectRoles: ["owner"], + creatorRoles: ["principal-investigator", "project-admin", "institution-admin"], + allowedExternalDomains: ["partner-lab.org"], + visibilityByClassification: { + open: ["public", "institutional", "private"], + controlled: ["institutional", "private"], + "restricted-human-subjects": ["private"], + }, + templates: { + "controlled-study": { + id: "controlled-study", + allowedClassifications: ["controlled", "restricted-human-subjects"], + requiredMetadataFields: ["retentionPlan"], + requiredProjectRoles: ["data-steward"], + requiredControls: ["auditTrail", "objectGrantReview"], + }, + }, + }, + users: [ + { + id: "user-pi-ada", + type: "internal", + projectCreator: true, + email: "ada@northbridge.edu", + mfaAt: "2026-06-01T08:00:00Z", + verifiedAffiliations: [{ institutionId: "northbridge", status: "verified" }], + identifiers: [{ type: "orcid", value: "0000-0002-1825-0097", status: "verified" }], + }, + { + id: "user-steward-lin", + type: "internal", + email: "lin@northbridge.edu", + verifiedAffiliations: [{ institutionId: "northbridge", status: "verified" }], + identifiers: [{ type: "orcid", value: "0000-0001-5555-1212", status: "verified" }], + }, + { + id: "user-ext-ren", + type: "external", + email: "ren@partner-lab.org", + training: { restrictedData: "current" }, + verifiedAffiliations: [{ institutionId: "partner-lab", status: "verified" }], + identifiers: [{ type: "orcid", value: "0000-0003-9999-8888", status: "verified" }], + }, + ], + request: { + requestId: "provision-1", + projectId: "project-neuro-qc", + name: "Neuro QC Consortium", + requesterId: "user-pi-ada", + institutionId: "northbridge", + templateId: "controlled-study", + dataClassification: "controlled", + visibility: "institutional", + metadata: { + projectName: "Neuro QC Consortium", + projectPurpose: "Coordinate reproducible quality-control notebooks for multi-site neuroimaging studies.", + discipline: "neuroscience", + institutionId: "northbridge", + dataClassification: "controlled", + retentionPlan: "retain-seven-years", + }, + controls: { + auditTrail: true, + objectGrantReview: true, + }, + roleAssignments: [ + { userId: "user-pi-ada", role: "owner", scope: "project" }, + { userId: "user-steward-lin", role: "data-steward", scope: "project" }, + { userId: "user-ext-ren", role: "viewer", scope: "project" }, + ], + objectGrants: [ + { principalId: "user-pi-ada", objectType: "workspace", permissions: ["admin"] }, + { principalId: "user-steward-lin", objectType: "controlled-dataset", permissions: ["read", "review"] }, + { principalId: "user-ext-ren", objectType: "manuscript", permissions: ["read"] }, + ], + externalCollaborators: ["user-ext-ren"], + approvals: [{ type: "sponsor-review", status: "approved", subjectId: "project-neuro-qc" }], + auditEvents: [ + { type: "provision-requested", actorId: "user-pi-ada", at: "2026-06-01T08:03:00Z" }, + { type: "baseline-evaluated", actorId: "system", at: "2026-06-01T08:04:00Z" }, + ], + }, + }; + + return { + ...packet, + ...overrides, + policy: { ...packet.policy, ...(overrides.policy || {}) }, + request: { ...packet.request, ...(overrides.request || {}) }, + }; +} + +function testReadyControlledProject() { + const result = evaluateProjectProvisioning(basePacket()); + + assert.equal(result.decision, "provision-ready"); + assert.equal(result.counts.blocker, 0); + assert.equal(result.publicSummary.visibility, "institutional"); +} + +function testRestrictedProjectCannotStartPublic() { + const packet = basePacket({ + request: { + dataClassification: "restricted-human-subjects", + visibility: "public", + metadata: { + projectName: "Neuro QC Consortium", + projectPurpose: "Coordinate reproducible quality-control notebooks for multi-site neuroimaging studies.", + discipline: "neuroscience", + institutionId: "northbridge", + dataClassification: "restricted-human-subjects", + retentionPlan: "retain-seven-years", + irbProtocolId: "IRB-2026-17", + dataUseAgreementId: "DUA-99", + }, + }, + }); + const result = evaluateProjectProvisioning(packet); + + assert.equal(result.decision, "hold-provisioning"); + assert.ok(result.findings.some((finding) => finding.code === "VISIBILITY_CLASSIFICATION_CONFLICT")); +} + +function testRequesterAuthorityAndMfaAreRequired() { + const packet = basePacket(); + packet.users[0].projectCreator = false; + packet.users[0].mfaAt = "2026-05-01T08:00:00Z"; + packet.request.roleAssignments = packet.request.roleAssignments.filter((assignment) => assignment.userId !== "user-pi-ada"); + + const result = evaluateProjectProvisioning(packet); + + assert.equal(result.decision, "hold-provisioning"); + assert.ok(result.findings.some((finding) => finding.code === "REQUESTER_AUTHORITY_MISSING")); + assert.ok(result.findings.some((finding) => finding.code === "REQUESTER_MFA_STALE")); +} + +function testExternalRestrictedGrantNeedsAgreement() { + const packet = basePacket({ + request: { + dataClassification: "restricted-human-subjects", + visibility: "private", + metadata: { + projectName: "Neuro QC Consortium", + projectPurpose: "Coordinate reproducible quality-control notebooks for multi-site neuroimaging studies.", + discipline: "neuroscience", + institutionId: "northbridge", + dataClassification: "restricted-human-subjects", + retentionPlan: "retain-seven-years", + irbProtocolId: "IRB-2026-17", + dataUseAgreementId: "DUA-99", + }, + objectGrants: [ + { principalId: "user-ext-ren", objectType: "restricted-dataset", permissions: ["read", "export"] }, + ], + approvals: [], + }, + }); + const result = evaluateProjectProvisioning(packet); + + assert.equal(result.decision, "hold-provisioning"); + assert.ok(result.findings.some((finding) => finding.code === "EXTERNAL_RESTRICTED_DATA_APPROVAL_MISSING")); +} + +function testMissingTemplateControlBlocksProvisioning() { + const packet = basePacket(); + packet.request.controls.objectGrantReview = false; + const result = evaluateProjectProvisioning(packet); + + assert.equal(result.decision, "hold-provisioning"); + assert.ok(result.findings.some((finding) => finding.code === "TEMPLATE_CONTROL_MISSING")); +} + +function testDeterministicDigest() { + const first = evaluateProjectProvisioning(basePacket()); + const second = evaluateProjectProvisioning(basePacket()); + + assert.equal(first.auditDigest, second.auditDigest); +} + +testReadyControlledProject(); +testRestrictedProjectCannotStartPublic(); +testRequesterAuthorityAndMfaAreRequired(); +testExternalRestrictedGrantNeedsAgreement(); +testMissingTemplateControlBlocksProvisioning(); +testDeterministicDigest(); + +console.log("project-provisioning-baseline-guard tests passed");