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
51 changes: 51 additions & 0 deletions enterprise-audit-signal-router/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Enterprise Audit Signal Router

A dependency-free Enterprise Tooling milestone for SCIBASE issue #19. It gives institutional admins a deterministic way to turn project activity into dashboard metrics, signed integration events, compliance alerts, and export packets for repositories, journals, and funders.

## What is included

- `src/index.js` — core library for workspace normalization, dashboard aggregation, compliance checks, REST/API catalog generation, signed webhook routing, export packet creation, and an end-to-end enterprise brief.
- `src/cli.js` — CLI demo that reads the sample fixture and prints an audit summary.
- `sample/enterprise-fixture.json` — representative university/corporate R&D workspace with public/private projects, contributors, API clients, mandates, DOI/ORCID/citation metadata, and events.
- `test/enterprise-audit-signal-router.test.js` — Node test coverage for every issue capability.
- `docs/demo.svg` and `docs/demo.mp4` — short visual demo artifacts.

## Requirement mapping

| Issue #19 capability | Implementation evidence |
| --- | --- |
| Admin dashboards for organization-wide project oversight | `buildAdminDashboard()` reports total/public/private projects, projects by department/lab, custom tags, and dashboard hash. |
| Contributor analytics, activity heatmaps, top researchers, and cross-lab collaborations | `contributorAnalytics` ranks researchers, computes activity heat, and records cross-lab collaboration counts. |
| Usage stats for logins, submissions, storage, and compute | `usageStats` aggregates logins, submissions, storage GB, and compute hours across the workspace. |
| Productivity metrics for lab output, AI reviews, and peer reviews | `productivityMetrics` tracks projects per lab, AI reviews generated, and peer reviews completed. |
| Compliance tracking for funder mandates, open access, and reproducibility scores | `evaluateCompliance()` flags missing funder/open-access/reproducibility evidence and emits compliance labels. |
| Secure RESTful API integration with repositories, LMS, ELNs, HRIS, and ORCID | `buildApiCatalog()` defines scoped REST endpoints, integration readiness for DSpace/Invenio/Canvas/Moodle/ELN/HRIS/ORCID, and security controls. |
| Webhooks for project creation, publication, and review events | `routeEnterpriseEvents()` creates HMAC-signed deliveries with deterministic payloads and destination routing. |
| Export pipelines for preprints, indexed repositories, journals, and funders | `buildExportPacket()` prepares arXiv, bioRxiv, Zenodo, PubMed Central, NIH RePORTER, UKRI, or custom packets. |
| Formatting plugins with DOI, ORCID, citation, and version preservation | Export packets include manuscript formats, DOI, ORCID list, citation text, tags, funder mandates, version history, files, and a packet hash. |

## Run verification

```bash
cd enterprise-audit-signal-router
npm run check
```

Expected result: six Node tests pass, then the CLI demo prints the institution, project visibility counts, top researcher, compliance risk count, webhook delivery count, export packet count, and audit hash.

## Demo output

```text
Enterprise Audit Signal Router Demo
Institution: Midlands Research Office
Projects: 2 (1 public / 1 private)
Top researcher: Ada Kim
Compliance risks: 1
Webhook deliveries: 16
Export packets: 2
Audit hash: <deterministic hash prefix>
```

## AI-assisted disclosure

This contribution was produced with AI assistance and manually reviewed/verified before submission.
Binary file added enterprise-audit-signal-router/docs/demo.mp4
Binary file not shown.
33 changes: 33 additions & 0 deletions enterprise-audit-signal-router/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.
12 changes: 12 additions & 0 deletions enterprise-audit-signal-router/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "enterprise-audit-signal-router",
"version": "0.1.0",
"description": "Dependency-free enterprise tooling module for admin dashboards, secure APIs/webhooks, and research export pipelines.",
"type": "module",
"private": true,
"scripts": {
"check": "npm test && npm run demo",
"demo": "node src/cli.js",
"test": "node --test test/*.test.js"
}
}
63 changes: 63 additions & 0 deletions enterprise-audit-signal-router/sample/enterprise-fixture.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"institution": {
"id": "midlands-research-office",
"name": "Midlands Research Office",
"departments": ["Bioengineering", "Climate Systems", "Materials Lab"],
"apiClients": [
{"id": "dspace-sync", "system": "DSpace", "scopes": ["projects:read", "exports:write"]},
{"id": "canvas-lms", "system": "Canvas", "scopes": ["projects:read", "reviews:read"]},
{"id": "orcid-hris", "system": "ORCID-HRIS", "scopes": ["contributors:sync"]}
],
"webhookSecret": "institutional-secret"
},
"contributors": [
{"id": "r-ada", "name": "Ada Kim", "department": "Bioengineering", "orcid": "0000-0002-1111-2222", "lab": "Bio-AI", "logins": 22},
{"id": "r-linus", "name": "Linus Park", "department": "Climate Systems", "orcid": "0000-0003-3333-4444", "lab": "Climate Risk", "logins": 17},
{"id": "r-marie", "name": "Marie Choi", "department": "Materials Lab", "orcid": "0000-0001-5555-6666", "lab": "NanoLab", "logins": 11}
],
"projects": [
{
"id": "proj-open-catalyst",
"title": "Open Catalyst Reproducibility",
"visibility": "public",
"department": "Materials Lab",
"lab": "NanoLab",
"tags": ["GRANT-TRACKED", "DOCTORAL WORK"],
"contributors": ["r-marie", "r-ada"],
"storageGb": 184,
"computeHours": 96,
"submissions": 4,
"aiReviews": 8,
"peerReviews": 6,
"funderMandates": ["NIH data sharing"],
"openAccess": true,
"reproducibilityScore": 0.91,
"doi": "10.5555/scibase.catalyst.2026",
"citations": ["Kim A, Choi M. Open catalyst reproducibility. 2026."],
"versions": ["v0.1 protocol", "v1.0 preprint"],
"events": ["project.created", "review.completed", "publication.released"]
},
{
"id": "proj-private-climate",
"title": "Private Climate Model Review",
"visibility": "private",
"department": "Climate Systems",
"lab": "Climate Risk",
"tags": ["BUSINESS-UNIT-RD"],
"contributors": ["r-linus"],
"storageGb": 640,
"computeHours": 420,
"submissions": 2,
"aiReviews": 11,
"peerReviews": 1,
"funderMandates": ["Horizon EU open data"],
"openAccess": false,
"reproducibilityScore": 0.68,
"doi": null,
"citations": ["Park L. Private climate model review. 2026."],
"versions": ["internal-draft"],
"events": ["project.created", "review.completed"]
}
],
"usageWindow": "2026-05"
}
19 changes: 19 additions & 0 deletions enterprise-audit-signal-router/src/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { buildEnterpriseToolingBrief } from './index.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const fixturePath = path.join(__dirname, '..', 'sample', 'enterprise-fixture.json');
const fixture = JSON.parse(fs.readFileSync(fixturePath, 'utf8'));
const brief = buildEnterpriseToolingBrief(fixture);

console.log('Enterprise Audit Signal Router Demo');
console.log(`Institution: ${brief.institution}`);
console.log(`Projects: ${brief.dashboard.projectCounts.total} (${brief.dashboard.projectCounts.public} public / ${brief.dashboard.projectCounts.private} private)`);
console.log(`Top researcher: ${brief.dashboard.contributorAnalytics.topResearchers[0].name}`);
console.log(`Compliance risks: ${brief.dashboard.complianceTracking.filter((item) => item.status === 'attention-required').length}`);
console.log(`Webhook deliveries: ${brief.routedEvents.reduce((sum, route) => sum + route.deliveries.length, 0)}`);
console.log(`Export packets: ${brief.exportPackets.length}`);
console.log(`Audit hash: ${brief.auditHash.slice(0, 16)}`);
Loading