Skip to content

Commit f112dbf

Browse files
authored
Merge pull request #793 from objectstack-ai/copilot/fix-iso-27001-compliance-gaps
2 parents 8d187ba + 9bc437c commit f112dbf

13 files changed

Lines changed: 2318 additions & 12 deletions

ROADMAP.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,31 @@ business/custom objects, aligning with industry best practices (e.g., ServiceNow
543543
- [ ] GDPR/CCPA compliance utilities (right to erasure, data export)
544544
- [ ] Change management and approval workflows for schema changes
545545

546+
### 6.5 ISO 27001:2022 Compliance
547+
548+
> **Goal:** Full schema coverage for ISO 27001:2022 Annex A controls to support certification readiness.
549+
550+
#### 6.5.1 High Priority (Certification Blockers) — ✅ Schema Complete
551+
552+
- [x] **Incident Response Protocol** (A.5.24–A.5.28) — `system/incident-response.zod.ts`: Incident classification, severity grading, response phases, notification matrix, escalation policies
553+
- [x] **Audit Scheduling & Finding Tracking** (A.5.35) — `system/compliance.zod.ts`: AuditScheduleSchema, AuditFindingSchema for independent review and remediation tracking
554+
- [x] **Change Management Security Approval** (A.8.32) — `system/change-management.zod.ts`: SecurityImpactAssessment with risk level, data classification, security reviewer workflow
555+
556+
#### 6.5.2 Medium Priority (Compliance Completeness) — ✅ Schema Complete
557+
558+
- [x] **Supplier Security Assessment** (A.5.19–A.5.22) — `system/supplier-security.zod.ts`: Supplier risk levels, security requirements, assessment lifecycle, remediation tracking
559+
- [x] **Information Security Training** (A.6.3) — `system/training.zod.ts`: Training courses, completion records, organizational training plans with recertification
560+
561+
#### 6.5.3 Medium Priority (Pending)
562+
563+
- [ ] **OAuth Scope Binding** (A.8.1) — API endpoint schema with required OAuth scopes
564+
- [ ] **Permission Registry** (A.8.2) — Transform `manifest.permissions` from `string[]` to structured registry enum
565+
566+
#### 6.5.4 Low Priority (Enhancements)
567+
568+
- [ ] Permission delegation and temporary privilege elevation protocol (AWS STS-style)
569+
- [ ] Device trust policy extensions
570+
546571
---
547572

548573
## Phase 7: AI & Intelligence (🔴 Planned)

packages/spec/src/system/change-management.test.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,4 +653,120 @@ describe('ChangeRequestSchema', () => {
653653

654654
expect(() => ChangeRequestSchema.parse(rolledBackChange)).not.toThrow();
655655
});
656+
657+
it('should accept change with security impact assessment (A.8.32)', () => {
658+
const changeWithSecurityImpact = {
659+
id: 'CHG-2024-SEC-001',
660+
title: 'API Gateway Configuration Change',
661+
description: 'Update API gateway security headers',
662+
type: 'normal',
663+
priority: 'high',
664+
status: 'approved',
665+
requestedBy: 'security_team',
666+
requestedAt: Date.now(),
667+
impact: {
668+
level: 'high',
669+
affectedSystems: ['api-gateway'],
670+
},
671+
implementation: {
672+
description: 'Update security headers',
673+
steps: [
674+
{
675+
order: 1,
676+
description: 'Deploy configuration',
677+
estimatedMinutes: 10,
678+
},
679+
],
680+
},
681+
rollbackPlan: {
682+
description: 'Revert configuration',
683+
steps: [
684+
{
685+
order: 1,
686+
description: 'Restore previous config',
687+
estimatedMinutes: 5,
688+
},
689+
],
690+
},
691+
securityImpact: {
692+
assessed: true,
693+
riskLevel: 'high',
694+
affectedDataClassifications: ['pii', 'confidential'],
695+
requiresSecurityApproval: true,
696+
reviewedBy: 'ciso',
697+
reviewedAt: Date.now(),
698+
reviewNotes: 'Approved with monitoring requirement',
699+
},
700+
};
701+
702+
const parsed = ChangeRequestSchema.parse(changeWithSecurityImpact);
703+
expect(parsed.securityImpact?.assessed).toBe(true);
704+
expect(parsed.securityImpact?.riskLevel).toBe('high');
705+
expect(parsed.securityImpact?.requiresSecurityApproval).toBe(true);
706+
});
707+
708+
it('should accept change with minimal security impact', () => {
709+
const change = {
710+
id: 'CHG-2024-SEC-002',
711+
title: 'Minor UI Change',
712+
description: 'Update button color',
713+
type: 'standard',
714+
priority: 'low',
715+
status: 'draft',
716+
requestedBy: 'user_123',
717+
requestedAt: Date.now(),
718+
impact: {
719+
level: 'low',
720+
affectedSystems: ['ui'],
721+
},
722+
implementation: {
723+
description: 'Update CSS',
724+
steps: [{ order: 1, description: 'Deploy', estimatedMinutes: 5 }],
725+
},
726+
rollbackPlan: {
727+
description: 'Revert CSS',
728+
steps: [{ order: 1, description: 'Revert', estimatedMinutes: 5 }],
729+
},
730+
securityImpact: {
731+
assessed: true,
732+
riskLevel: 'none',
733+
},
734+
};
735+
736+
const parsed = ChangeRequestSchema.parse(change);
737+
expect(parsed.securityImpact?.riskLevel).toBe('none');
738+
expect(parsed.securityImpact?.requiresSecurityApproval).toBe(false);
739+
});
740+
741+
it('should accept all security risk levels', () => {
742+
const levels = ['none', 'low', 'medium', 'high', 'critical'] as const;
743+
744+
levels.forEach((riskLevel) => {
745+
const change = {
746+
id: `CHG-${riskLevel}`,
747+
title: 'Test',
748+
description: 'Test',
749+
type: 'standard',
750+
priority: 'low',
751+
status: 'draft',
752+
requestedBy: 'user',
753+
requestedAt: Date.now(),
754+
impact: { level: 'low', affectedSystems: ['test'] },
755+
implementation: {
756+
description: 'Test',
757+
steps: [{ order: 1, description: 'Test', estimatedMinutes: 5 }],
758+
},
759+
rollbackPlan: {
760+
description: 'Test',
761+
steps: [{ order: 1, description: 'Test', estimatedMinutes: 5 }],
762+
},
763+
securityImpact: {
764+
assessed: true,
765+
riskLevel,
766+
},
767+
};
768+
769+
expect(() => ChangeRequestSchema.parse(change)).not.toThrow();
770+
});
771+
});
656772
});

packages/spec/src/system/change-management.zod.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

33
import { z } from 'zod';
4+
import { DataClassificationSchema } from './security-context.zod';
45

56
/**
67
* Change Type Enum
@@ -319,6 +320,52 @@ export const ChangeRequestSchema = z.object({
319320
actualEnd: z.number().optional().describe('Actual end time'),
320321
}).optional().describe('Schedule'),
321322

323+
/**
324+
* Security impact assessment for the change (A.8.32)
325+
*/
326+
securityImpact: z.object({
327+
/**
328+
* Whether a security impact assessment has been performed
329+
*/
330+
assessed: z.boolean().describe('Whether security impact has been assessed'),
331+
332+
/**
333+
* Security risk level of this change
334+
*/
335+
riskLevel: z.enum(['none', 'low', 'medium', 'high', 'critical']).optional()
336+
.describe('Security risk level'),
337+
338+
/**
339+
* Data classifications affected by this change
340+
*/
341+
affectedDataClassifications: z.array(DataClassificationSchema)
342+
.optional().describe('Affected data classifications'),
343+
344+
/**
345+
* Whether the change requires security team approval
346+
*/
347+
requiresSecurityApproval: z.boolean().default(false)
348+
.describe('Whether security team approval is required'),
349+
350+
/**
351+
* Security reviewer user ID
352+
*/
353+
reviewedBy: z.string().optional()
354+
.describe('Security reviewer user ID'),
355+
356+
/**
357+
* Security review completion timestamp (Unix milliseconds)
358+
*/
359+
reviewedAt: z.number().optional()
360+
.describe('Security review timestamp'),
361+
362+
/**
363+
* Security review notes or conditions
364+
*/
365+
reviewNotes: z.string().optional()
366+
.describe('Security review notes or conditions'),
367+
}).optional().describe('Security impact assessment per ISO 27001:2022 A.8.32'),
368+
322369
/**
323370
* Approval workflow configuration
324371
*/

0 commit comments

Comments
 (0)