Update 10 files
This commit is contained in:
1 parent
28a3c6121a
commit
28680e396e
10 files changed
+46
-108
No files matched your search
@@ -3,20 +3,11 @@
|
||||
* This document lists all data entities, their purposes, legal basis, and retention categories
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
interface DataEntity {
|
||||
name: string;
|
||||
dataCategories: string[];
|
||||
legalBasis: string;
|
||||
purpose: string;
|
||||
retentionCategory: string;
|
||||
notes?: string;
|
||||
}
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
// Core data model definition
|
||||
const dataModel: DataEntity[] = [
|
||||
const dataModel = [
|
||||
{
|
||||
name: "User",
|
||||
dataCategories: ["firstName", "lastName", "email", "role", "createdAt"],
|
||||
@@ -112,12 +103,12 @@ const dataModel: DataEntity[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export function generateDataModel(outputPath: string = "docs/legal"): void {
|
||||
function generateDataModel(outputPath = "docs/legal") {
|
||||
if (!fs.existsSync(outputPath)) {
|
||||
fs.mkdirSync(outputPath, { recursive: true });
|
||||
}
|
||||
|
||||
const lines: string[] = [
|
||||
const lines = [
|
||||
"# Data Model Documentation",
|
||||
"",
|
||||
"**Status**: Schema Reference for ExaMetra (Module L)",
|
||||
@@ -166,7 +157,7 @@ export function generateDataModel(outputPath: string = "docs/legal"): void {
|
||||
"",
|
||||
`Generated: ${new Date().toISOString()}`,
|
||||
"Source: ExaMetra Prisma schema (Module L)",
|
||||
];
|
||||
);
|
||||
|
||||
const filePath = path.join(outputPath, "DATA_MODEL.md");
|
||||
fs.writeFileSync(filePath, lines.join("\n"), "utf-8");
|
||||
|
||||
@@ -3,26 +3,15 @@
|
||||
* Plain-language German, based on school configuration
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
interface PrivacyNoticeParams {
|
||||
schoolName: string;
|
||||
dpoName: string;
|
||||
dpoEmail: string;
|
||||
schultragerName: string;
|
||||
bundesland: string;
|
||||
}
|
||||
|
||||
export function generatePrivacyNotice(
|
||||
params: PrivacyNoticeParams,
|
||||
outputPath: string = "docs/legal"
|
||||
): void {
|
||||
function generatePrivacyNotice(params, outputPath = "docs/legal") {
|
||||
if (!fs.existsSync(outputPath)) {
|
||||
fs.mkdirSync(outputPath, { recursive: true });
|
||||
}
|
||||
|
||||
const lines: string[] = [
|
||||
const lines = [
|
||||
"# Datenschutzerklärung",
|
||||
"# (Privacy Notice for Parents & Students)",
|
||||
"",
|
||||
@@ -139,7 +128,7 @@ export function generatePrivacyNotice(
|
||||
console.log(`[v0] Generated privacy notice at ${filePath}`);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
if (process.argv[1] && path.resolve(process.argv[1]) === new URL(import.meta.url).pathname) {
|
||||
generatePrivacyNotice({
|
||||
schoolName: "Gymnasium Berlin",
|
||||
dpoName: "Max Mustermann",
|
||||
|
||||
@@ -4,20 +4,10 @@
|
||||
* German legal document for school's DPO review
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
interface RopaEntry {
|
||||
name: string;
|
||||
purposes: string[];
|
||||
dataCategories: string[];
|
||||
recipients: string[];
|
||||
retentionPeriod: string;
|
||||
legalBasis: string;
|
||||
securityMeasures: string[];
|
||||
}
|
||||
|
||||
const ropas: RopaEntry[] = [
|
||||
const ropas = [
|
||||
{
|
||||
name: "Student Information Management",
|
||||
purposes: [
|
||||
@@ -126,12 +116,12 @@ const ropas: RopaEntry[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export function generateRopa(outputPath: string = "docs/legal"): void {
|
||||
function generateRopa(outputPath = "docs/legal") {
|
||||
if (!fs.existsSync(outputPath)) {
|
||||
fs.mkdirSync(outputPath, { recursive: true });
|
||||
}
|
||||
|
||||
const lines: string[] = [
|
||||
const lines = [
|
||||
"# Verzeichnis von Verarbeitungstätigkeiten",
|
||||
"# (Records of Processing Activities - Art. 30 GDPR)",
|
||||
"",
|
||||
@@ -198,7 +188,7 @@ export function generateRopa(outputPath: string = "docs/legal"): void {
|
||||
"",
|
||||
`**Generiert**: ${new Date().toISOString()}`,
|
||||
"**Quelle**: ExaMetra Module L - Compliance Framework",
|
||||
];
|
||||
);
|
||||
|
||||
const filePath = path.join(
|
||||
outputPath,
|
||||
|
||||
@@ -6,18 +6,11 @@
|
||||
* Usage: npx ts-node scripts/run-retention-job.ts
|
||||
*/
|
||||
|
||||
const { PrismaClient } = require("@prisma/client");
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import path from "node:path";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
interface FlaggedRecord {
|
||||
entityType: string;
|
||||
entityId: string;
|
||||
dataCategory: string;
|
||||
flaggedAt: Date;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check records for each school and flag those exceeding retention period
|
||||
*/
|
||||
@@ -32,7 +25,7 @@ async function runRetentionJob() {
|
||||
});
|
||||
|
||||
let totalFlagged = 0;
|
||||
const report: { school: string; flagged: number }[] = [];
|
||||
const report = [];
|
||||
|
||||
for (const school of schools) {
|
||||
const schoolFlagged = await flagExpiredRecordsForSchool(school.id);
|
||||
@@ -75,7 +68,7 @@ async function runRetentionJob() {
|
||||
/**
|
||||
* Flag expired records for a specific school
|
||||
*/
|
||||
async function flagExpiredRecordsForSchool(schoolId: string): Promise<number> {
|
||||
async function flagExpiredRecordsForSchool(schoolId) {
|
||||
// Get all retention policies for this school
|
||||
const policies = await prisma.dataRetentionPolicy.findMany({
|
||||
where: { schoolId },
|
||||
@@ -106,11 +99,7 @@ async function flagExpiredRecordsForSchool(schoolId: string): Promise<number> {
|
||||
/**
|
||||
* Flag records of a specific category that are older than expiryDate
|
||||
*/
|
||||
async function flagRecordsByCategory(
|
||||
schoolId: string,
|
||||
dataCategory: string,
|
||||
expiryDate: Date
|
||||
): Promise<number> {
|
||||
async function flagRecordsByCategory(schoolId, dataCategory, expiryDate) {
|
||||
let flaggedCount = 0;
|
||||
|
||||
try {
|
||||
@@ -201,11 +190,7 @@ async function flagRecordsByCategory(
|
||||
/**
|
||||
* Generic function to flag expired records by entity type
|
||||
*/
|
||||
async function flagRecordsByEntityType(
|
||||
schoolId: string,
|
||||
entityType: string,
|
||||
expiryDate: Date
|
||||
): Promise<number> {
|
||||
async function flagRecordsByEntityType(schoolId, entityType, expiryDate) {
|
||||
// Check if records of this type already have deletion flags
|
||||
const alreadyFlagged = await prisma.deletionFlag.findMany({
|
||||
where: {
|
||||
@@ -255,7 +240,7 @@ async function flagRecordsByEntityType(
|
||||
}
|
||||
|
||||
// Run the job if this script is executed directly
|
||||
if (require.main === module) {
|
||||
if (process.argv[1] && path.resolve(process.argv[1]) === new URL(import.meta.url).pathname) {
|
||||
runRetentionJob()
|
||||
.then((result) => {
|
||||
console.log(
|
||||
@@ -270,4 +255,4 @@ if (require.main === module) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { runRetentionJob, flagExpiredRecordsForSchool };
|
||||
export { runRetentionJob, flagExpiredRecordsForSchool };
|
||||
Reference in new issue
Block a user