@cloudstreamsoftware/claude-tools 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -37
- package/agents/INDEX.md +183 -0
- package/agents/architect.md +247 -0
- package/agents/build-error-resolver.md +555 -0
- package/agents/catalyst-deployer.md +132 -0
- package/agents/code-reviewer.md +121 -0
- package/agents/compliance-auditor.md +148 -0
- package/agents/creator-architect.md +395 -0
- package/agents/deluge-reviewer.md +98 -0
- package/agents/doc-updater.md +471 -0
- package/agents/e2e-runner.md +711 -0
- package/agents/planner.md +122 -0
- package/agents/refactor-cleaner.md +309 -0
- package/agents/security-reviewer.md +582 -0
- package/agents/tdd-guide.md +302 -0
- package/config/versions.json +63 -0
- package/dist/hooks/hooks.json +209 -0
- package/dist/index.js +47 -0
- package/dist/lib/asset-value.js +609 -0
- package/dist/lib/client-manager.js +300 -0
- package/dist/lib/command-matcher.js +242 -0
- package/dist/lib/cross-session-patterns.js +754 -0
- package/dist/lib/intent-classifier.js +1075 -0
- package/dist/lib/package-manager.js +374 -0
- package/dist/lib/recommendation-engine.js +597 -0
- package/dist/lib/session-memory.js +489 -0
- package/dist/lib/skill-effectiveness.js +486 -0
- package/dist/lib/skill-matcher.js +595 -0
- package/dist/lib/tutorial-metrics.js +242 -0
- package/dist/lib/tutorial-progress.js +209 -0
- package/dist/lib/tutorial-renderer.js +431 -0
- package/dist/lib/utils.js +380 -0
- package/dist/lib/verify-formatter.js +143 -0
- package/dist/lib/workflow-state.js +249 -0
- package/hooks/hooks.json +209 -0
- package/package.json +5 -1
- package/scripts/aggregate-sessions.js +290 -0
- package/scripts/branch-name-validator.js +291 -0
- package/scripts/build.js +101 -0
- package/scripts/commands/client-switch.js +231 -0
- package/scripts/deprecate-skill.js +610 -0
- package/scripts/diagnose.js +324 -0
- package/scripts/doc-freshness.js +168 -0
- package/scripts/generate-weekly-digest.js +393 -0
- package/scripts/health-check.js +270 -0
- package/scripts/hooks/credential-check.js +101 -0
- package/scripts/hooks/evaluate-session.js +81 -0
- package/scripts/hooks/pre-compact.js +66 -0
- package/scripts/hooks/prompt-analyzer.js +276 -0
- package/scripts/hooks/prompt-router.js +422 -0
- package/scripts/hooks/quality-gate-enforcer.js +371 -0
- package/scripts/hooks/session-end.js +156 -0
- package/scripts/hooks/session-start.js +195 -0
- package/scripts/hooks/skill-injector.js +333 -0
- package/scripts/hooks/suggest-compact.js +58 -0
- package/scripts/lib/asset-value.js +609 -0
- package/scripts/lib/client-manager.js +300 -0
- package/scripts/lib/command-matcher.js +242 -0
- package/scripts/lib/cross-session-patterns.js +754 -0
- package/scripts/lib/intent-classifier.js +1075 -0
- package/scripts/lib/package-manager.js +374 -0
- package/scripts/lib/recommendation-engine.js +597 -0
- package/scripts/lib/session-memory.js +489 -0
- package/scripts/lib/skill-effectiveness.js +486 -0
- package/scripts/lib/skill-matcher.js +595 -0
- package/scripts/lib/tutorial-metrics.js +242 -0
- package/scripts/lib/tutorial-progress.js +209 -0
- package/scripts/lib/tutorial-renderer.js +431 -0
- package/scripts/lib/utils.js +380 -0
- package/scripts/lib/verify-formatter.js +143 -0
- package/scripts/lib/workflow-state.js +249 -0
- package/scripts/onboard.js +363 -0
- package/scripts/quarterly-report.js +692 -0
- package/scripts/setup-package-manager.js +204 -0
- package/scripts/sync-upstream.js +391 -0
- package/scripts/test.js +108 -0
- package/scripts/tutorial-runner.js +351 -0
- package/scripts/validate-all.js +201 -0
- package/scripts/verifiers/agents.js +245 -0
- package/scripts/verifiers/config.js +186 -0
- package/scripts/verifiers/environment.js +123 -0
- package/scripts/verifiers/hooks.js +188 -0
- package/scripts/verifiers/index.js +38 -0
- package/scripts/verifiers/persistence.js +140 -0
- package/scripts/verifiers/plugin.js +215 -0
- package/scripts/verifiers/skills.js +209 -0
- package/scripts/verify-setup.js +164 -0
- package/skills/INDEX.md +157 -0
- package/skills/backend-patterns/SKILL.md +586 -0
- package/skills/backend-patterns/catalyst-patterns.md +128 -0
- package/skills/bigquery-patterns/SKILL.md +27 -0
- package/skills/bigquery-patterns/performance-optimization.md +518 -0
- package/skills/bigquery-patterns/query-patterns.md +372 -0
- package/skills/bigquery-patterns/schema-design.md +78 -0
- package/skills/cloudstream-project-template/SKILL.md +20 -0
- package/skills/cloudstream-project-template/structure.md +65 -0
- package/skills/coding-standards/SKILL.md +524 -0
- package/skills/coding-standards/deluge-standards.md +83 -0
- package/skills/compliance-patterns/SKILL.md +28 -0
- package/skills/compliance-patterns/hipaa/audit-requirements.md +251 -0
- package/skills/compliance-patterns/hipaa/baa-process.md +298 -0
- package/skills/compliance-patterns/hipaa/data-archival-strategy.md +387 -0
- package/skills/compliance-patterns/hipaa/phi-handling.md +52 -0
- package/skills/compliance-patterns/pci-dss/saq-a-requirements.md +307 -0
- package/skills/compliance-patterns/pci-dss/tokenization-patterns.md +382 -0
- package/skills/compliance-patterns/pci-dss/zoho-checkout-patterns.md +56 -0
- package/skills/compliance-patterns/soc2/access-controls.md +344 -0
- package/skills/compliance-patterns/soc2/audit-logging.md +458 -0
- package/skills/compliance-patterns/soc2/change-management.md +403 -0
- package/skills/compliance-patterns/soc2/deluge-execution-logging.md +407 -0
- package/skills/consultancy-workflows/SKILL.md +19 -0
- package/skills/consultancy-workflows/client-isolation.md +21 -0
- package/skills/consultancy-workflows/documentation-automation.md +454 -0
- package/skills/consultancy-workflows/handoff-procedures.md +257 -0
- package/skills/consultancy-workflows/knowledge-capture.md +513 -0
- package/skills/consultancy-workflows/time-tracking.md +26 -0
- package/skills/continuous-learning/SKILL.md +84 -0
- package/skills/continuous-learning/config.json +18 -0
- package/skills/continuous-learning/evaluate-session.sh +60 -0
- package/skills/continuous-learning-v2/SKILL.md +126 -0
- package/skills/continuous-learning-v2/config.json +61 -0
- package/skills/frontend-patterns/SKILL.md +635 -0
- package/skills/frontend-patterns/zoho-widget-patterns.md +103 -0
- package/skills/gcp-data-engineering/SKILL.md +36 -0
- package/skills/gcp-data-engineering/bigquery/performance-optimization.md +337 -0
- package/skills/gcp-data-engineering/dataflow/error-handling.md +496 -0
- package/skills/gcp-data-engineering/dataflow/pipeline-patterns.md +444 -0
- package/skills/gcp-data-engineering/dbt/model-organization.md +63 -0
- package/skills/gcp-data-engineering/dbt/testing-patterns.md +503 -0
- package/skills/gcp-data-engineering/medallion-architecture/bronze-layer.md +60 -0
- package/skills/gcp-data-engineering/medallion-architecture/gold-layer.md +311 -0
- package/skills/gcp-data-engineering/medallion-architecture/layer-transitions.md +517 -0
- package/skills/gcp-data-engineering/medallion-architecture/silver-layer.md +305 -0
- package/skills/gcp-data-engineering/zoho-to-gcp/data-extraction.md +543 -0
- package/skills/gcp-data-engineering/zoho-to-gcp/real-time-vs-batch.md +337 -0
- package/skills/security-review/SKILL.md +498 -0
- package/skills/security-review/compliance-checklist.md +53 -0
- package/skills/strategic-compact/SKILL.md +67 -0
- package/skills/tdd-workflow/SKILL.md +413 -0
- package/skills/tdd-workflow/zoho-testing.md +124 -0
- package/skills/tutorial/SKILL.md +249 -0
- package/skills/tutorial/docs/ACCESSIBILITY.md +169 -0
- package/skills/tutorial/lessons/00-philosophy-and-workflow.md +198 -0
- package/skills/tutorial/lessons/01-basics.md +81 -0
- package/skills/tutorial/lessons/02-training.md +86 -0
- package/skills/tutorial/lessons/03-commands.md +109 -0
- package/skills/tutorial/lessons/04-workflows.md +115 -0
- package/skills/tutorial/lessons/05-compliance.md +116 -0
- package/skills/tutorial/lessons/06-zoho.md +121 -0
- package/skills/tutorial/lessons/07-hooks-system.md +277 -0
- package/skills/tutorial/lessons/08-mcp-servers.md +316 -0
- package/skills/tutorial/lessons/09-client-management.md +215 -0
- package/skills/tutorial/lessons/10-testing-e2e.md +260 -0
- package/skills/tutorial/lessons/11-skills-deep-dive.md +272 -0
- package/skills/tutorial/lessons/12-rules-system.md +326 -0
- package/skills/tutorial/lessons/13-golden-standard-graduation.md +213 -0
- package/skills/tutorial/lessons/14-fork-setup-and-sync.md +312 -0
- package/skills/tutorial/lessons/15-living-examples-system.md +221 -0
- package/skills/tutorial/tracks/accelerated/README.md +134 -0
- package/skills/tutorial/tracks/accelerated/assessment/checkpoint-1.md +161 -0
- package/skills/tutorial/tracks/accelerated/assessment/checkpoint-2.md +175 -0
- package/skills/tutorial/tracks/accelerated/day-1-core-concepts.md +234 -0
- package/skills/tutorial/tracks/accelerated/day-2-essential-commands.md +270 -0
- package/skills/tutorial/tracks/accelerated/day-3-workflow-mastery.md +305 -0
- package/skills/tutorial/tracks/accelerated/day-4-compliance-zoho.md +304 -0
- package/skills/tutorial/tracks/accelerated/day-5-hooks-skills.md +344 -0
- package/skills/tutorial/tracks/accelerated/day-6-client-testing.md +386 -0
- package/skills/tutorial/tracks/accelerated/day-7-graduation.md +369 -0
- package/skills/zoho-patterns/CHANGELOG.md +108 -0
- package/skills/zoho-patterns/SKILL.md +446 -0
- package/skills/zoho-patterns/analytics/dashboard-patterns.md +352 -0
- package/skills/zoho-patterns/analytics/zoho-to-bigquery-pipeline.md +427 -0
- package/skills/zoho-patterns/catalyst/appsail-deployment.md +349 -0
- package/skills/zoho-patterns/catalyst/context-close-patterns.md +354 -0
- package/skills/zoho-patterns/catalyst/cron-batch-processing.md +374 -0
- package/skills/zoho-patterns/catalyst/function-patterns.md +439 -0
- package/skills/zoho-patterns/creator/form-design.md +304 -0
- package/skills/zoho-patterns/creator/publish-api-patterns.md +313 -0
- package/skills/zoho-patterns/creator/widget-integration.md +306 -0
- package/skills/zoho-patterns/creator/workflow-automation.md +253 -0
- package/skills/zoho-patterns/deluge/api-patterns.md +468 -0
- package/skills/zoho-patterns/deluge/batch-processing.md +403 -0
- package/skills/zoho-patterns/deluge/cross-app-integration.md +356 -0
- package/skills/zoho-patterns/deluge/error-handling.md +423 -0
- package/skills/zoho-patterns/deluge/syntax-reference.md +65 -0
- package/skills/zoho-patterns/integration/cors-proxy-architecture.md +426 -0
- package/skills/zoho-patterns/integration/crm-books-native-sync.md +277 -0
- package/skills/zoho-patterns/integration/oauth-token-management.md +461 -0
- package/skills/zoho-patterns/integration/zoho-flow-patterns.md +334 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# HIPAA Data Archival Strategy
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Zoho Creator retains audit log data for only **1 year** before automatic deletion. HIPAA requires **6 years** of retention. This document defines the automated archival strategy using Zoho Catalyst Cron functions to export audit data to Google BigQuery for long-term, compliant storage.
|
|
6
|
+
|
|
7
|
+
> **WARNING**: If the monthly archival job fails silently for 12+ months, audit data will be permanently lost with no recovery option. Monitoring and alerting are NOT optional.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Architecture Overview
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Zoho Creator (ePHI Forms)
|
|
15
|
+
|
|
|
16
|
+
| (Deluge audit logging on every action)
|
|
17
|
+
v
|
|
18
|
+
HIPAA_Audit_Log Form (Creator)
|
|
19
|
+
|
|
|
20
|
+
| (Monthly Catalyst Cron - Day 5 of each month)
|
|
21
|
+
v
|
|
22
|
+
Catalyst Serverless Function
|
|
23
|
+
|
|
|
24
|
+
| (Batch export via Creator API → BigQuery API)
|
|
25
|
+
v
|
|
26
|
+
Google BigQuery (Long-term storage)
|
|
27
|
+
|
|
|
28
|
+
| (Retention policy: 6 years + 90 days)
|
|
29
|
+
v
|
|
30
|
+
Automated Purge (records older than 6 years + 90 days)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Monthly Automated Export Process
|
|
36
|
+
|
|
37
|
+
### Schedule
|
|
38
|
+
|
|
39
|
+
- **When**: 5th of every month at 02:00 UTC
|
|
40
|
+
- **What**: Export all audit records from the previous calendar month
|
|
41
|
+
- **Why Day 5**: Allows buffer for late-arriving records and avoids month-end processing
|
|
42
|
+
|
|
43
|
+
### Catalyst Cron Function
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
// File: functions/hipaa_audit_archival/index.js
|
|
47
|
+
// Catalyst Cron Function - Scheduled monthly
|
|
48
|
+
|
|
49
|
+
const catalyst = require('zcatalyst-sdk-node');
|
|
50
|
+
const { BigQuery } = require('@google-cloud/bigquery');
|
|
51
|
+
|
|
52
|
+
module.exports = async (cronDetails, context) => {
|
|
53
|
+
const app = catalyst.initialize(context);
|
|
54
|
+
|
|
55
|
+
// Calculate date range for previous month
|
|
56
|
+
const now = new Date();
|
|
57
|
+
const startDate = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
58
|
+
const endDate = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59);
|
|
59
|
+
|
|
60
|
+
const batchId = `ARCH-${startDate.getFullYear()}${String(startDate.getMonth()+1).padStart(2,'0')}-${Date.now()}`;
|
|
61
|
+
|
|
62
|
+
console.log(`Starting archival batch: ${batchId}`);
|
|
63
|
+
console.log(`Date range: ${startDate.toISOString()} to ${endDate.toISOString()}`);
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
// Fetch audit records from Creator
|
|
67
|
+
const records = await fetchAuditRecords(startDate, endDate);
|
|
68
|
+
console.log(`Records to archive: ${records.length}`);
|
|
69
|
+
|
|
70
|
+
if (records.length === 0) {
|
|
71
|
+
await sendAlert('WARNING', `No audit records found for ${batchId}. Verify logging is active.`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Transform and upload to BigQuery
|
|
76
|
+
const bigquery = new BigQuery({ projectId: process.env.GCP_PROJECT_ID });
|
|
77
|
+
const dataset = bigquery.dataset(process.env.BQ_DATASET);
|
|
78
|
+
const table = dataset.table('hipaa_audit_logs');
|
|
79
|
+
|
|
80
|
+
// Batch insert (max 10,000 rows per insert)
|
|
81
|
+
const batches = chunkArray(records, 10000);
|
|
82
|
+
for (const batch of batches) {
|
|
83
|
+
const rows = batch.map(r => transformRecord(r, batchId));
|
|
84
|
+
await table.insert(rows);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Mark records as archived in Creator
|
|
88
|
+
await markRecordsArchived(records, batchId);
|
|
89
|
+
|
|
90
|
+
// Log success
|
|
91
|
+
await logArchivalResult(batchId, records.length, 'SUCCESS');
|
|
92
|
+
|
|
93
|
+
console.log(`Archival complete: ${records.length} records in batch ${batchId}`);
|
|
94
|
+
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error(`Archival FAILED: ${error.message}`);
|
|
97
|
+
await sendAlert('CRITICAL', `Audit archival failed for batch ${batchId}: ${error.message}`);
|
|
98
|
+
await logArchivalResult(batchId, 0, 'FAILED', error.message);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
function transformRecord(record, batchId) {
|
|
103
|
+
return {
|
|
104
|
+
audit_id: String(record.Audit_ID),
|
|
105
|
+
timestamp: new Date(record.Timestamp).toISOString(),
|
|
106
|
+
user_email: record.User_Email,
|
|
107
|
+
user_role: record.User_Role,
|
|
108
|
+
ip_address: record.IP_Address,
|
|
109
|
+
session_id: record.Session_ID,
|
|
110
|
+
action_type: record.Action_Type,
|
|
111
|
+
form_name: record.Form_Name,
|
|
112
|
+
record_id: record.Record_ID,
|
|
113
|
+
field_name: record.Field_Name || null,
|
|
114
|
+
old_value: record.Old_Value || null,
|
|
115
|
+
new_value: record.New_Value || null,
|
|
116
|
+
justification: record.Justification || null,
|
|
117
|
+
client_id: record.Client_ID,
|
|
118
|
+
source_org: process.env.ZOHO_ORG_ID,
|
|
119
|
+
archive_date: new Date().toISOString(),
|
|
120
|
+
archive_batch_id: batchId
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function chunkArray(array, size) {
|
|
125
|
+
const chunks = [];
|
|
126
|
+
for (let i = 0; i < array.length; i += size) {
|
|
127
|
+
chunks.push(array.slice(i, i + size));
|
|
128
|
+
}
|
|
129
|
+
return chunks;
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Deluge Companion Script (Record Fetching)
|
|
134
|
+
|
|
135
|
+
```deluge
|
|
136
|
+
// Workflow: Fetch audit records for archival
|
|
137
|
+
// Called by Catalyst function via Creator API
|
|
138
|
+
|
|
139
|
+
searchCriteria = "(Timestamp >= \"" + startDate + "\" && Timestamp <= \"" + endDate + "\" && Archived == false)";
|
|
140
|
+
records = zoho.creator.getRecords("your-app", "HIPAA_Audit_Log", searchCriteria, 1, 200);
|
|
141
|
+
|
|
142
|
+
// Note: Creator API returns max 200 records per call
|
|
143
|
+
// Implement pagination for larger datasets
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Data Format Specification
|
|
149
|
+
|
|
150
|
+
### Export Format: JSON Lines (JSONL)
|
|
151
|
+
|
|
152
|
+
Each record is exported as a single JSON object per line:
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{"audit_id":"12345","timestamp":"2025-01-15T14:30:22Z","user_email":"nurse@hospital.com","user_role":"Clinical Staff","ip_address":"10.0.1.45","session_id":"sess_abc123","action_type":"Access","form_name":"Patient_Records","record_id":67890,"field_name":null,"old_value":null,"new_value":null,"justification":null,"client_id":"CLT-001","source_org":"org_xyz","archive_date":"2025-02-05T02:00:15Z","archive_batch_id":"ARCH-202501-1707091215000"}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Field Encryption
|
|
159
|
+
|
|
160
|
+
> **WARNING**: old_value and new_value fields may contain ePHI. These MUST be encrypted at the application layer before storage in BigQuery.
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
const crypto = require('crypto');
|
|
164
|
+
|
|
165
|
+
function encryptValue(plaintext, key) {
|
|
166
|
+
if (!plaintext) return null;
|
|
167
|
+
const iv = crypto.randomBytes(16);
|
|
168
|
+
const cipher = crypto.createCipheriv('aes-256-gcm', Buffer.from(key, 'hex'), iv);
|
|
169
|
+
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
|
|
170
|
+
encrypted += cipher.final('hex');
|
|
171
|
+
const authTag = cipher.getAuthTag().toString('hex');
|
|
172
|
+
return `${iv.toString('hex')}:${authTag}:${encrypted}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function decryptValue(encryptedText, key) {
|
|
176
|
+
if (!encryptedText) return null;
|
|
177
|
+
const [ivHex, authTagHex, encrypted] = encryptedText.split(':');
|
|
178
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', Buffer.from(key, 'hex'), Buffer.from(ivHex, 'hex'));
|
|
179
|
+
decipher.setAuthTag(Buffer.from(authTagHex, 'hex'));
|
|
180
|
+
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
181
|
+
decrypted += decipher.final('utf8');
|
|
182
|
+
return decrypted;
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Encryption at Rest
|
|
189
|
+
|
|
190
|
+
### BigQuery Default Encryption
|
|
191
|
+
|
|
192
|
+
- **Algorithm**: AES-256
|
|
193
|
+
- **Key Management**: Google-managed keys (default) or Customer-Managed Encryption Keys (CMEK)
|
|
194
|
+
- **Recommendation**: Use CMEK for healthcare clients via Cloud KMS
|
|
195
|
+
|
|
196
|
+
### CMEK Configuration
|
|
197
|
+
|
|
198
|
+
```sql
|
|
199
|
+
-- Create dataset with CMEK
|
|
200
|
+
CREATE SCHEMA `project.hipaa_audit_dataset`
|
|
201
|
+
OPTIONS (
|
|
202
|
+
default_kms_key_name = 'projects/PROJECT/locations/LOCATION/keyRings/RING/cryptoKeys/KEY'
|
|
203
|
+
);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Key Rotation
|
|
207
|
+
|
|
208
|
+
- Google-managed keys: Automatic rotation
|
|
209
|
+
- CMEK: Configure 90-day automatic rotation in Cloud KMS
|
|
210
|
+
- Application-layer keys: Rotate annually, re-encrypt on rotation
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Retention Policy Configuration
|
|
215
|
+
|
|
216
|
+
### BigQuery Table-Level Retention
|
|
217
|
+
|
|
218
|
+
```sql
|
|
219
|
+
-- Set 6-year + 90-day retention (2,281 days)
|
|
220
|
+
ALTER TABLE `project.dataset.hipaa_audit_logs`
|
|
221
|
+
SET OPTIONS (
|
|
222
|
+
partition_expiration_days = 2281
|
|
223
|
+
);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Dataset-Level Default Retention
|
|
227
|
+
|
|
228
|
+
```sql
|
|
229
|
+
ALTER SCHEMA `project.hipaa_audit_dataset`
|
|
230
|
+
SET OPTIONS (
|
|
231
|
+
default_partition_expiration_days = 2281
|
|
232
|
+
);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
> **WARNING**: Test retention policy on a non-production dataset first. Incorrect configuration can result in premature data deletion with no recovery.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Access Controls on Archived Data
|
|
240
|
+
|
|
241
|
+
### IAM Roles
|
|
242
|
+
|
|
243
|
+
| Role | Access Level | Assigned To |
|
|
244
|
+
|---|---|---|
|
|
245
|
+
| `bigquery.dataViewer` | Read-only queries | Compliance team |
|
|
246
|
+
| `bigquery.dataEditor` | Insert new records | Archival service account |
|
|
247
|
+
| `bigquery.admin` | Full control | CloudStream admin (break-glass only) |
|
|
248
|
+
| `bigquery.jobUser` | Run queries | Auditors (time-limited) |
|
|
249
|
+
|
|
250
|
+
### Service Account for Archival
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"type": "service_account",
|
|
255
|
+
"project_id": "client-hipaa-project",
|
|
256
|
+
"purpose": "HIPAA audit archival from Catalyst",
|
|
257
|
+
"roles": [
|
|
258
|
+
"roles/bigquery.dataEditor",
|
|
259
|
+
"roles/bigquery.jobUser"
|
|
260
|
+
],
|
|
261
|
+
"restrictions": {
|
|
262
|
+
"dataset": "hipaa_audit_dataset",
|
|
263
|
+
"tables": ["hipaa_audit_logs", "archival_metadata"]
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Access Logging
|
|
269
|
+
|
|
270
|
+
Enable BigQuery Data Access audit logs:
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
Cloud Console → IAM & Admin → Audit Logs
|
|
274
|
+
→ BigQuery API → Enable Data Read, Data Write
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Annual Purge of Data Beyond 6 Years
|
|
280
|
+
|
|
281
|
+
### Automated Purge Process
|
|
282
|
+
|
|
283
|
+
> **WARNING**: Purging is IRREVERSIBLE. Verify retention calculations thoroughly before enabling automated purge.
|
|
284
|
+
|
|
285
|
+
```sql
|
|
286
|
+
-- Identify records eligible for purge (older than 6 years + 90 day buffer)
|
|
287
|
+
SELECT COUNT(*) as records_to_purge,
|
|
288
|
+
MIN(timestamp) as oldest_record,
|
|
289
|
+
MAX(timestamp) as newest_eligible
|
|
290
|
+
FROM `project.dataset.hipaa_audit_logs`
|
|
291
|
+
WHERE timestamp < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 2281 DAY);
|
|
292
|
+
|
|
293
|
+
-- Execute purge (run ONLY after verification)
|
|
294
|
+
DELETE FROM `project.dataset.hipaa_audit_logs`
|
|
295
|
+
WHERE timestamp < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 2281 DAY);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Purge Pre-Checks
|
|
299
|
+
|
|
300
|
+
1. Verify no active litigation holds on the data
|
|
301
|
+
2. Confirm no pending audit requests covering the date range
|
|
302
|
+
3. Get written approval from client compliance officer
|
|
303
|
+
4. Take a final backup before purge (Cloud Storage, 30-day hold)
|
|
304
|
+
5. Document purge action in compliance log
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Disaster Recovery for Archived Audits
|
|
309
|
+
|
|
310
|
+
### Backup Strategy
|
|
311
|
+
|
|
312
|
+
| Layer | Method | RPO | RTO |
|
|
313
|
+
|---|---|---|---|
|
|
314
|
+
| BigQuery native | Cross-region replication | 0 (synchronous) | Minutes |
|
|
315
|
+
| Monthly snapshot | Export to Cloud Storage (Nearline) | 30 days | Hours |
|
|
316
|
+
| Annual cold backup | Cloud Storage (Archive class) | 1 year | 24 hours |
|
|
317
|
+
|
|
318
|
+
### Monthly Snapshot Export
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
# Export monthly snapshot to Cloud Storage
|
|
322
|
+
bq extract \
|
|
323
|
+
--destination_format=AVRO \
|
|
324
|
+
--compression=SNAPPY \
|
|
325
|
+
'project:dataset.hipaa_audit_logs$20250101' \
|
|
326
|
+
'gs://client-hipaa-backups/monthly/2025-01/audit_logs_*.avro'
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Recovery Procedure
|
|
330
|
+
|
|
331
|
+
1. Identify the gap in BigQuery data
|
|
332
|
+
2. Locate the appropriate backup in Cloud Storage
|
|
333
|
+
3. Load backup data into a staging table
|
|
334
|
+
4. Verify record counts and checksums
|
|
335
|
+
5. Insert missing records into the production table
|
|
336
|
+
6. Validate completeness with date-range queries
|
|
337
|
+
7. Document the recovery in the incident log
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Monitoring and Alerting
|
|
342
|
+
|
|
343
|
+
### Critical Alerts (Immediate Response Required)
|
|
344
|
+
|
|
345
|
+
| Alert | Condition | Action |
|
|
346
|
+
|---|---|---|
|
|
347
|
+
| Archival job failed | Cron execution error | Investigate and re-run within 48 hours |
|
|
348
|
+
| No records archived | Zero records in monthly batch | Verify audit logging is active |
|
|
349
|
+
| Record count mismatch | Creator count != BigQuery count | Investigate missing records |
|
|
350
|
+
| BigQuery write errors | Insert failures | Check permissions and quotas |
|
|
351
|
+
|
|
352
|
+
### Weekly Health Check Query
|
|
353
|
+
|
|
354
|
+
```sql
|
|
355
|
+
-- Verify monthly archival completeness
|
|
356
|
+
SELECT
|
|
357
|
+
FORMAT_TIMESTAMP('%Y-%m', archive_date) as archive_month,
|
|
358
|
+
COUNT(*) as records_archived,
|
|
359
|
+
MIN(timestamp) as earliest_record,
|
|
360
|
+
MAX(timestamp) as latest_record
|
|
361
|
+
FROM `project.dataset.hipaa_audit_logs`
|
|
362
|
+
GROUP BY archive_month
|
|
363
|
+
ORDER BY archive_month DESC
|
|
364
|
+
LIMIT 13;
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Cost Estimation
|
|
370
|
+
|
|
371
|
+
### BigQuery Storage Costs
|
|
372
|
+
|
|
373
|
+
| Storage Tier | Price | When Applied |
|
|
374
|
+
|---|---|---|
|
|
375
|
+
| Active storage | $0.02/GB/month | First 90 days after last modification |
|
|
376
|
+
| Long-term storage | $0.01/GB/month | After 90 days unmodified |
|
|
377
|
+
| Query costs | $5/TB scanned | Per query (on-demand pricing) |
|
|
378
|
+
|
|
379
|
+
### Typical Healthcare Client Costs
|
|
380
|
+
|
|
381
|
+
| Client Size | Monthly Records | Annual Storage | Annual Query | Total Annual |
|
|
382
|
+
|---|---|---|---|---|
|
|
383
|
+
| Small practice | 5,000 | ~$0.50 | ~$1.00 | ~$1.50 |
|
|
384
|
+
| Mid-size clinic | 50,000 | ~$5.00 | ~$5.00 | ~$10.00 |
|
|
385
|
+
| Hospital system | 500,000 | ~$50.00 | ~$25.00 | ~$75.00 |
|
|
386
|
+
|
|
387
|
+
> These costs are negligible compared to HIPAA non-compliance penalties. Bill as infrastructure pass-through plus management overhead.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# PHI Handling in Zoho
|
|
2
|
+
|
|
3
|
+
## Identifying ePHI Fields
|
|
4
|
+
Electronic Protected Health Information includes:
|
|
5
|
+
- Patient names, addresses, dates (birth, admission, discharge, death)
|
|
6
|
+
- Phone/fax numbers, email addresses
|
|
7
|
+
- SSN, medical record numbers, health plan IDs
|
|
8
|
+
- Account numbers, certificate/license numbers
|
|
9
|
+
- Device identifiers, URLs, IP addresses
|
|
10
|
+
- Biometric identifiers, photographs
|
|
11
|
+
- Any unique identifying number/code
|
|
12
|
+
|
|
13
|
+
## Creator Field Configuration
|
|
14
|
+
```
|
|
15
|
+
Field: Patient_Name [PHI]
|
|
16
|
+
- Encryption: ENABLED
|
|
17
|
+
- Access: Roles [Doctor, Nurse, Admin]
|
|
18
|
+
- Audit: ON (log all reads and writes)
|
|
19
|
+
- Reports: HIDDEN by default
|
|
20
|
+
|
|
21
|
+
Field: Diagnosis_Code [PHI]
|
|
22
|
+
- Encryption: ENABLED
|
|
23
|
+
- Access: Roles [Doctor]
|
|
24
|
+
- Audit: ON
|
|
25
|
+
- Reports: Aggregates only
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Audit Logging Pattern (Deluge)
|
|
29
|
+
|
|
30
|
+
> See `audit-requirements.md` for the full HIPAA_Audit_Log schema and BigQuery archival strategy.
|
|
31
|
+
|
|
32
|
+
```deluge
|
|
33
|
+
// Log all PHI access - fields match HIPAA_Audit_Log form schema
|
|
34
|
+
auditMap = Map();
|
|
35
|
+
auditMap.put("Timestamp", zoho.currenttime);
|
|
36
|
+
auditMap.put("User_Email", zoho.loginuserid);
|
|
37
|
+
auditMap.put("User_Role", zoho.loginuserRole);
|
|
38
|
+
auditMap.put("IP_Address", zoho.ipaddress);
|
|
39
|
+
auditMap.put("Action_Type", "Access");
|
|
40
|
+
auditMap.put("Form_Name", "Patient_Records");
|
|
41
|
+
auditMap.put("Record_ID", input.Record_ID);
|
|
42
|
+
auditMap.put("Field_Name", "Patient_Name,Diagnosis_Code");
|
|
43
|
+
|
|
44
|
+
zoho.creator.createRecord("app", "HIPAA_Audit_Log", auditMap);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Data Archival Strategy
|
|
48
|
+
Creator retains audit data for only 1 year. Implement:
|
|
49
|
+
1. Monthly export of audit logs to GCS (Cloud Storage)
|
|
50
|
+
2. BigQuery table for long-term audit retention (6+ years for HIPAA)
|
|
51
|
+
3. Scheduled Catalyst Cron function for automated export
|
|
52
|
+
4. Verify exports before Creator auto-deletion window
|