From 98445dbd3546d1a9cbe50ea9036eb06e9788ee26 Mon Sep 17 00:00:00 2001 From: cw <88217123+2bf@users.noreply.github.com> Date: Tue, 19 May 2026 18:08:34 -0700 Subject: [PATCH] Add challenge IP redaction gate --- challenge-ip-redaction-gate/README.md | 42 ++++++ challenge-ip-redaction-gate/demo.js | 76 +++++++++++ challenge-ip-redaction-gate/demo.mp4 | Bin 0 -> 58283 bytes challenge-ip-redaction-gate/demo.svg | 13 ++ challenge-ip-redaction-gate/index.js | 180 ++++++++++++++++++++++++++ challenge-ip-redaction-gate/test.js | 145 +++++++++++++++++++++ 6 files changed, 456 insertions(+) create mode 100644 challenge-ip-redaction-gate/README.md create mode 100644 challenge-ip-redaction-gate/demo.js create mode 100644 challenge-ip-redaction-gate/demo.mp4 create mode 100644 challenge-ip-redaction-gate/demo.svg create mode 100644 challenge-ip-redaction-gate/index.js create mode 100644 challenge-ip-redaction-gate/test.js diff --git a/challenge-ip-redaction-gate/README.md b/challenge-ip-redaction-gate/README.md new file mode 100644 index 00000000..dbe6e0b9 --- /dev/null +++ b/challenge-ip-redaction-gate/README.md @@ -0,0 +1,42 @@ +# Challenge IP Redaction Gate + +Self-contained milestone for SCIBASE.AI issue #18, Scientific Bounty System. + +This module protects solver intellectual property during scientific bounty +evaluation. It gives sponsors and reviewers useful evidence packets while +withholding unpaid proprietary content until the challenge has funded and +settled the relevant award. + +## What It Covers + +- Sponsor preview packets that redact unpaid solver IP. +- Reviewer packets with NDA and role-aware disclosure controls. +- Private challenge and NDA readiness checks before sponsor access. +- Settlement-gated IP transfer after funded payout. +- Deterministic audit digests for arbitration-ready evidence. +- Synthetic sample data only; no network, credentials, or external services. + +## Files + +- `index.js` - disclosure policy engine. +- `demo.js` - terminal demo for sponsor/reviewer/settlement flows. +- `test.js` - dependency-free regression tests. +- `demo.mp4` - short demo artifact for the bounty review flow. + +## Run + +```sh +node challenge-ip-redaction-gate/test.js +node challenge-ip-redaction-gate/demo.js +``` + +## Requirement Map + +| Issue #18 Requirement | Implementation | +| --- | --- | +| Challenge posting portal with public/private support | `validateChallengeDisclosure()` blocks private or sensitive challenge previews unless NDA and IP policies are configured. | +| Secure submission engine | `buildDisclosurePacket()` turns submission artifacts into role-specific evidence packets without exposing unpaid protected content. | +| Anonymous or named participation | Submission `team.displayMode` and audit metadata keep the solver identity separate from artifact disclosure decisions. | +| Arbitration and reward distribution | Deterministic `auditDigest` values and `withheldArtifacts` create reviewer/arbitrator evidence without leaking raw IP. | +| IP management options | `settlement.status === "funded_settled"` is required before sponsor packets disclose protected content or mark `ipTransferReady`. | +| Feedback loop between submitters and sponsors | Packets include `requiredActions` explaining the exact gating reason and remediation path. | diff --git a/challenge-ip-redaction-gate/demo.js b/challenge-ip-redaction-gate/demo.js new file mode 100644 index 00000000..1d74bbd0 --- /dev/null +++ b/challenge-ip-redaction-gate/demo.js @@ -0,0 +1,76 @@ +const { buildDisclosurePacket } = require("./index") + +const challenge = { + id: "bio-marker-forecast-2026", + visibility: "private", + ndaRequired: true, + ipPolicy: "transfer_on_payout", + evaluationMode: "reviewer_only", + sensitiveDomains: ["single-cell-rna", "clinical"], +} + +const submission = { + id: "sub-lab-17", + team: { + id: "solver-team-aurora", + displayMode: "anonymous_until_shortlist", + }, + artifacts: [ + { + id: "whitepaper", + title: "Biomarker Method Summary", + kind: "document", + confidential: true, + ipProtected: false, + content: "Feature-selection method, validation cohort, and benchmark summary.", + safeSummary: "High-level biomarker validation summary is available to NDA reviewers.", + }, + { + id: "model-weights", + title: "Trained Model Weights", + kind: "model", + confidential: true, + ipProtected: true, + content: "solver-owned weight matrix and proprietary feature ranking formula", + safeSummary: "Model weights are committed by hash and withheld until payout settlement.", + }, + { + id: "clinical-table", + title: "Clinical Feature Table", + kind: "dataset", + confidential: true, + containsHumanSubjectsData: true, + ipProtected: false, + content: "synthetic patient-level feature rows", + safeSummary: "Human-subjects table is held pending ethics clearance.", + }, + ], +} + +const sponsorBeforePayout = buildDisclosurePacket({ + challenge, + submission, + actor: { role: "sponsor", id: "sponsor-pharma", ndaSigned: true }, + settlement: { status: "under_review", ethicsCleared: false }, +}) + +const reviewerPacket = buildDisclosurePacket({ + challenge, + submission, + actor: { role: "reviewer", id: "reviewer-2", ndaSigned: true, clearance: "full" }, + settlement: { status: "under_review", ethicsCleared: true }, +}) + +const sponsorAfterSettlement = buildDisclosurePacket({ + challenge, + submission, + actor: { role: "sponsor", id: "sponsor-pharma", ndaSigned: true }, + settlement: { status: "funded_settled", ethicsCleared: true }, +}) + +console.log("Sponsor before payout") +console.log(JSON.stringify(sponsorBeforePayout, null, 2)) +console.log("\nReviewer packet") +console.log(JSON.stringify(reviewerPacket, null, 2)) +console.log("\nSponsor after funded settlement") +console.log(JSON.stringify(sponsorAfterSettlement, null, 2)) diff --git a/challenge-ip-redaction-gate/demo.mp4 b/challenge-ip-redaction-gate/demo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..ceeee2dc6feb2ff2abefe992e4bf9c319515cfa1 GIT binary patch literal 58283 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 Rp!)+B8%(z#o)~ + Challenge IP Redaction Gate demo slide + Demo summary for sponsor redaction, reviewer packet, settlement unlock, and test validation. + + + SCIBASE Scientific Bounty System + Challenge IP Redaction Gate + Sponsor preview - protected solver IP redacted + Reviewer packet - NDA access with audit digest + Funded settlement - IP transfer unlocks + Validation - node test.js - 6 tests passed + Dependency-free, synthetic-data-only, deterministic audit evidence. + diff --git a/challenge-ip-redaction-gate/index.js b/challenge-ip-redaction-gate/index.js new file mode 100644 index 00000000..a317e574 --- /dev/null +++ b/challenge-ip-redaction-gate/index.js @@ -0,0 +1,180 @@ +const crypto = require("node:crypto") + +const REDACTION_NOTICE = + "[REDACTED: solver IP withheld until funded settlement or authorized reviewer access]" + +function stableJson(value) { + if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]` + if (value && typeof value === "object") { + return `{${Object.keys(value) + .sort() + .map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`) + .join(",")}}` + } + return JSON.stringify(value) +} + +function digest(value) { + return crypto.createHash("sha256").update(stableJson(value)).digest("hex") +} + +function validateChallengeDisclosure(challenge) { + const requiredActions = [] + + if (!challenge.id) requiredActions.push("Add a stable challenge id.") + if (!challenge.ipPolicy) requiredActions.push("Define an IP policy.") + if (!challenge.evaluationMode) requiredActions.push("Define an evaluation mode.") + + if (challenge.visibility === "private" && !challenge.ndaRequired) { + requiredActions.push("Private challenges must require an NDA.") + } + + if ( + challenge.sensitiveDomains?.length > 0 && + challenge.evaluationMode === "open_preview" && + !challenge.ndaRequired + ) { + requiredActions.push( + "Sensitive-domain challenges need NDA-gated previews or reviewer-only packets.", + ) + } + + return { + ready: requiredActions.length === 0, + requiredActions, + } +} + +function actorCanViewProtectedIp(actor, challenge, settlement) { + if (actor.role === "sponsor") return settlement?.status === "funded_settled" + if (actor.role === "reviewer") return Boolean(actor.ndaSigned && actor.clearance === "full") + if (actor.role === "arbitrator") return Boolean(actor.ndaSigned) + return false +} + +function actorCanViewConfidential(actor, challenge) { + if (actor.role === "sponsor") return !challenge.ndaRequired || actor.ndaSigned + if (actor.role === "reviewer" || actor.role === "arbitrator") return actor.ndaSigned + return false +} + +function classifyArtifact(artifact, challenge, actor, settlement) { + if (artifact.ipProtected && !actorCanViewProtectedIp(actor, challenge, settlement)) { + return { + classification: "protected_ip_redacted", + discloseRaw: false, + reason: "Protected solver IP is withheld until funded settlement or authorized reviewer access.", + } + } + + if (artifact.confidential && !actorCanViewConfidential(actor, challenge)) { + return { + classification: "confidential_blocked", + discloseRaw: false, + reason: "Confidential artifact requires NDA-gated access.", + } + } + + if (artifact.containsHumanSubjectsData && actor.role === "sponsor" && !settlement?.ethicsCleared) { + return { + classification: "ethics_redacted", + discloseRaw: false, + reason: "Human-subjects data requires ethics clearance before sponsor disclosure.", + } + } + + return { + classification: "disclosed", + discloseRaw: true, + reason: "Actor is authorized for this artifact.", + } +} + +function redactArtifact(artifact, challenge, actor, settlement) { + const decision = classifyArtifact(artifact, challenge, actor, settlement) + const contentHash = digest({ + id: artifact.id, + title: artifact.title, + content: artifact.content, + }) + + if (decision.discloseRaw) { + return { + id: artifact.id, + title: artifact.title, + kind: artifact.kind, + classification: decision.classification, + content: artifact.content, + contentHash, + redacted: false, + } + } + + return { + id: artifact.id, + title: artifact.title, + kind: artifact.kind, + classification: decision.classification, + content: artifact.safeSummary || REDACTION_NOTICE, + contentHash, + redacted: true, + redactionReason: decision.reason, + } +} + +function buildDisclosurePacket({ challenge, submission, actor, settlement = {} }) { + const challengeReadiness = validateChallengeDisclosure(challenge) + const artifacts = submission.artifacts.map((artifact) => + redactArtifact(artifact, challenge, actor, settlement), + ) + const withheldArtifacts = artifacts.filter((artifact) => artifact.redacted) + const requiredActions = [...challengeReadiness.requiredActions] + + for (const artifact of withheldArtifacts) { + requiredActions.push(`${artifact.id}: ${artifact.redactionReason}`) + } + + const ipTransferReady = + actor.role === "sponsor" && + settlement.status === "funded_settled" && + challenge.ipPolicy === "transfer_on_payout" && + withheldArtifacts.length === 0 + + const packet = { + challengeId: challenge.id, + submissionId: submission.id, + actor: { + role: actor.role, + id: actor.id, + }, + team: { + id: submission.team.id, + displayMode: submission.team.displayMode, + }, + disclosureStatus: requiredActions.length === 0 ? "ready" : "gated", + ipTransferReady, + artifacts, + withheldArtifacts: withheldArtifacts.map((artifact) => ({ + id: artifact.id, + title: artifact.title, + classification: artifact.classification, + contentHash: artifact.contentHash, + reason: artifact.redactionReason, + })), + requiredActions, + } + + return { + ...packet, + auditDigest: digest(packet), + } +} + +module.exports = { + REDACTION_NOTICE, + buildDisclosurePacket, + classifyArtifact, + digest, + stableJson, + validateChallengeDisclosure, +} diff --git a/challenge-ip-redaction-gate/test.js b/challenge-ip-redaction-gate/test.js new file mode 100644 index 00000000..6bd8313f --- /dev/null +++ b/challenge-ip-redaction-gate/test.js @@ -0,0 +1,145 @@ +const assert = require("node:assert/strict") +const { + REDACTION_NOTICE, + buildDisclosurePacket, + digest, + validateChallengeDisclosure, +} = require("./index") + +function sampleChallenge(overrides = {}) { + return { + id: "quantum-noise-2026", + visibility: "private", + ndaRequired: true, + ipPolicy: "transfer_on_payout", + evaluationMode: "reviewer_only", + sensitiveDomains: ["quantum", "materials"], + ...overrides, + } +} + +function sampleSubmission() { + return { + id: "submission-42", + team: { + id: "solver-team", + displayMode: "anonymous_until_shortlist", + }, + artifacts: [ + { + id: "summary", + title: "Executive Summary", + kind: "document", + confidential: true, + ipProtected: false, + content: "A safe summary of the experiment design.", + }, + { + id: "solver-formula", + title: "Noise Reduction Formula", + kind: "notebook", + confidential: true, + ipProtected: true, + content: "proprietary coefficients and solver-owned algorithm", + safeSummary: "Formula committed by hash; raw notebook withheld until settlement.", + }, + ], + } +} + +function testSponsorPreviewRedactsUnpaidIp() { + const packet = buildDisclosurePacket({ + challenge: sampleChallenge(), + submission: sampleSubmission(), + actor: { role: "sponsor", id: "sponsor", ndaSigned: true }, + settlement: { status: "under_review" }, + }) + + const formula = packet.artifacts.find((artifact) => artifact.id === "solver-formula") + assert.equal(packet.disclosureStatus, "gated") + assert.equal(formula.redacted, true) + assert.equal(formula.content.includes("proprietary coefficients"), false) + assert.equal(packet.withheldArtifacts.length, 1) + assert.match(packet.requiredActions.join("\n"), /Protected solver IP/) +} + +function testReviewerWithClearanceCanInspectIpWithoutTransfer() { + const packet = buildDisclosurePacket({ + challenge: sampleChallenge(), + submission: sampleSubmission(), + actor: { role: "reviewer", id: "reviewer", ndaSigned: true, clearance: "full" }, + settlement: { status: "under_review" }, + }) + + const formula = packet.artifacts.find((artifact) => artifact.id === "solver-formula") + assert.equal(packet.disclosureStatus, "ready") + assert.equal(formula.redacted, false) + assert.equal(packet.ipTransferReady, false) +} + +function testSponsorSettlementUnlocksIpTransfer() { + const packet = buildDisclosurePacket({ + challenge: sampleChallenge(), + submission: sampleSubmission(), + actor: { role: "sponsor", id: "sponsor", ndaSigned: true }, + settlement: { status: "funded_settled" }, + }) + + const formula = packet.artifacts.find((artifact) => artifact.id === "solver-formula") + assert.equal(packet.disclosureStatus, "ready") + assert.equal(formula.redacted, false) + assert.equal(packet.ipTransferReady, true) +} + +function testPrivateChallengeRequiresNda() { + const readiness = validateChallengeDisclosure( + sampleChallenge({ visibility: "private", ndaRequired: false }), + ) + + assert.equal(readiness.ready, false) + assert.match(readiness.requiredActions.join("\n"), /Private challenges must require an NDA/) +} + +function testAuditDigestIsDeterministic() { + const input = { + challenge: sampleChallenge(), + submission: sampleSubmission(), + actor: { role: "sponsor", id: "sponsor", ndaSigned: true }, + settlement: { status: "under_review" }, + } + + const first = buildDisclosurePacket(input) + const second = buildDisclosurePacket(input) + assert.equal(first.auditDigest, second.auditDigest) + assert.equal(digest({ b: 2, a: 1 }), digest({ a: 1, b: 2 })) +} + +function testMissingNdaBlocksConfidentialArtifact() { + const packet = buildDisclosurePacket({ + challenge: sampleChallenge(), + submission: sampleSubmission(), + actor: { role: "sponsor", id: "sponsor", ndaSigned: false }, + settlement: { status: "funded_settled" }, + }) + + const summary = packet.artifacts.find((artifact) => artifact.id === "summary") + assert.equal(summary.redacted, true) + assert.equal(summary.content, REDACTION_NOTICE) + assert.match(packet.requiredActions.join("\n"), /Confidential artifact requires NDA/) +} + +const tests = [ + testSponsorPreviewRedactsUnpaidIp, + testReviewerWithClearanceCanInspectIpWithoutTransfer, + testSponsorSettlementUnlocksIpTransfer, + testPrivateChallengeRequiresNda, + testAuditDigestIsDeterministic, + testMissingNdaBlocksConfidentialArtifact, +] + +for (const test of tests) { + test() + console.log(`ok - ${test.name}`) +} + +console.log(`${tests.length} tests passed`)