Data Isolation

How TheCompanyApp ensures complete separation of company data.

Isolation Strategy

Core Principle: Every entity is scoped by companyID: UUID.

Enforcement: All data queries filtered by company identifier.

Company Scoping

Entity Schema

Every company-scoped entity includes:

  • companyID: UUID - Unique identifier for the company

  • Optional: companyName: String - Denormalized for display

Example (InventoryItem entity):

<entity name="InventoryItem">
    <attribute name="companyID" attributeType="UUID" usesScalarValueType="NO"/>
    <attribute name="itemCode" attributeType="String"/>
    <attribute name="itemName" attributeType="String"/>
    <!-- ... other attributes ... -->
</entity>

Fetch Requests

All fetches must include companyID predicate:

Correct:

Wrong (no scoping):

Never fetch across companies unless explicitly intended (e.g., admin view in future).

SwiftUI Integration

@FetchRequest with Dynamic Predicate:

Result: View only displays orders for selected company.

Cross-Company Protection

Scenario: User Has Multiple Companies

User: Alice Companies:

  • Company A (companyID: abc-123)

  • Company B (companyID: def-456)

Data:

  • 50 orders in Company A

  • 30 orders in Company B

View Company A:

View Company B:

No Cross-Contamination: Company A data never appears in Company B views.

Shared Company Isolation

Scenario: Alice owns Company A, shares with Bob.

Alice's Perspective (Owner)

Fetch:

Result: Alice sees all company data (owner privilege + participant edits).

Bob's Perspective (Participant)

Fetch:

Result: Bob sees identical data to Alice.

Isolation: Bob cannot see Alice's other companies (Company B, Company C, etc.).

User-Specific Data: UserPass

Exception: UserPass is isolated by user, not shared.

Alice's UserPass:

Bob's UserPass:

Isolation Mechanism: Stored in Private Database, which is user-scoped by iCloud.

Fetch:

Isolation at CloudKit Level

Private Database

Scope: User-level

Data: User's owned companies + UserPass for all companies.

Access: Only the user (across their devices).

Example:

  • Alice's Private Database contains:

    • Company A (owned)

    • Company B (owned)

    • UserPass for Company A

    • UserPass for Company C (shared by Charlie, but Alice's credentials)

Shared Database

Scope: Share-level (per CKShare)

Data: Companies shared to user + all shared company data.

Access: Owner + participants of the specific share.

Example:

  • Alice's Shared Database contains:

    • Company C (shared by Charlie)

    • Company C's inventory, orders, etc.

    • NO access to Company D (shared to someone else, not Alice)

Zone-Level Isolation: Each CKShare creates a separate zone. User can only read zones they're invited to.

Testing Isolation

Unit Test Example:

Expected Result: Each company sees only its own data.

Preventing Accidental Leakage

Code Review Checklist

Static Analysis

Consider:

  • SwiftLint custom rule to detect fetch requests without predicates

  • Code review automation

Runtime Assertion

Use in development to catch errors.


Related: Security Model, Company Scopingarrow-up-right, Fetch Strategiesarrow-up-right

Last updated