@trohde/earos 1.0.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 +156 -0
- package/assets/init/.agents/skills/earos-artifact-gen/SKILL.md +106 -0
- package/assets/init/.agents/skills/earos-artifact-gen/references/interview-guide.md +313 -0
- package/assets/init/.agents/skills/earos-artifact-gen/references/output-guide.md +367 -0
- package/assets/init/.agents/skills/earos-assess/SKILL.md +212 -0
- package/assets/init/.agents/skills/earos-assess/references/calibration-benchmarks.md +160 -0
- package/assets/init/.agents/skills/earos-assess/references/output-templates.md +311 -0
- package/assets/init/.agents/skills/earos-assess/references/scoring-protocol.md +281 -0
- package/assets/init/.agents/skills/earos-calibrate/SKILL.md +153 -0
- package/assets/init/.agents/skills/earos-calibrate/references/agreement-metrics.md +188 -0
- package/assets/init/.agents/skills/earos-calibrate/references/calibration-protocol.md +263 -0
- package/assets/init/.agents/skills/earos-create/SKILL.md +257 -0
- package/assets/init/.agents/skills/earos-create/references/criterion-writing-guide.md +268 -0
- package/assets/init/.agents/skills/earos-create/references/dependency-rules.md +193 -0
- package/assets/init/.agents/skills/earos-create/references/rubric-interview-guide.md +123 -0
- package/assets/init/.agents/skills/earos-create/references/validation-checklist.md +238 -0
- package/assets/init/.agents/skills/earos-profile-author/SKILL.md +251 -0
- package/assets/init/.agents/skills/earos-profile-author/references/criterion-writing-guide.md +280 -0
- package/assets/init/.agents/skills/earos-profile-author/references/design-methods.md +158 -0
- package/assets/init/.agents/skills/earos-profile-author/references/profile-checklist.md +173 -0
- package/assets/init/.agents/skills/earos-remediate/SKILL.md +118 -0
- package/assets/init/.agents/skills/earos-remediate/references/output-template.md +199 -0
- package/assets/init/.agents/skills/earos-remediate/references/remediation-patterns.md +330 -0
- package/assets/init/.agents/skills/earos-report/SKILL.md +85 -0
- package/assets/init/.agents/skills/earos-report/references/portfolio-template.md +181 -0
- package/assets/init/.agents/skills/earos-report/references/single-artifact-template.md +168 -0
- package/assets/init/.agents/skills/earos-review/SKILL.md +130 -0
- package/assets/init/.agents/skills/earos-review/references/challenge-patterns.md +163 -0
- package/assets/init/.agents/skills/earos-review/references/output-template.md +180 -0
- package/assets/init/.agents/skills/earos-template-fill/SKILL.md +177 -0
- package/assets/init/.agents/skills/earos-template-fill/references/evidence-writing-guide.md +186 -0
- package/assets/init/.agents/skills/earos-template-fill/references/section-rubric-mapping.md +200 -0
- package/assets/init/.agents/skills/earos-validate/SKILL.md +113 -0
- package/assets/init/.agents/skills/earos-validate/references/fix-patterns.md +281 -0
- package/assets/init/.agents/skills/earos-validate/references/validation-checks.md +287 -0
- package/assets/init/.claude/CLAUDE.md +4 -0
- package/assets/init/AGENTS.md +293 -0
- package/assets/init/CLAUDE.md +635 -0
- package/assets/init/README.md +507 -0
- package/assets/init/calibration/gold-set/.gitkeep +0 -0
- package/assets/init/calibration/results/.gitkeep +0 -0
- package/assets/init/core/core-meta-rubric.yaml +643 -0
- package/assets/init/docs/consistency-report.md +325 -0
- package/assets/init/docs/getting-started.md +194 -0
- package/assets/init/docs/profile-authoring-guide.md +51 -0
- package/assets/init/docs/terminology.md +126 -0
- package/assets/init/earos.manifest.yaml +104 -0
- package/assets/init/evaluations/.gitkeep +0 -0
- package/assets/init/examples/aws-event-driven-order-processing/artifact.yaml +2056 -0
- package/assets/init/examples/aws-event-driven-order-processing/evaluation.yaml +973 -0
- package/assets/init/examples/aws-event-driven-order-processing/report.md +244 -0
- package/assets/init/examples/example-solution-architecture.evaluation.yaml +136 -0
- package/assets/init/examples/multi-cloud-data-analytics/artifact.yaml +715 -0
- package/assets/init/overlays/data-governance.yaml +94 -0
- package/assets/init/overlays/regulatory.yaml +154 -0
- package/assets/init/overlays/security.yaml +92 -0
- package/assets/init/profiles/adr.yaml +225 -0
- package/assets/init/profiles/capability-map.yaml +223 -0
- package/assets/init/profiles/reference-architecture.yaml +426 -0
- package/assets/init/profiles/roadmap.yaml +205 -0
- package/assets/init/profiles/solution-architecture.yaml +227 -0
- package/assets/init/research/architecture-assessment-rubrics-research.docx +0 -0
- package/assets/init/research/architecture-assessment-rubrics-research.md +566 -0
- package/assets/init/research/reference-architecture-research.md +751 -0
- package/assets/init/standard/EAROS.md +1426 -0
- package/assets/init/standard/schemas/artifact.schema.json +1295 -0
- package/assets/init/standard/schemas/artifact.uischema.json +65 -0
- package/assets/init/standard/schemas/evaluation.schema.json +284 -0
- package/assets/init/standard/schemas/rubric.schema.json +383 -0
- package/assets/init/templates/evaluation-record.template.yaml +58 -0
- package/assets/init/templates/new-profile.template.yaml +65 -0
- package/bin.js +188 -0
- package/dist/assets/_basePickBy-BVu6YmSW.js +1 -0
- package/dist/assets/_baseUniq-CWRzQDz_.js +1 -0
- package/dist/assets/arc-CyDBhtDM.js +1 -0
- package/dist/assets/architectureDiagram-2XIMDMQ5-BH6O4dvN.js +36 -0
- package/dist/assets/blockDiagram-WCTKOSBZ-2xmwdjpg.js +132 -0
- package/dist/assets/c4Diagram-IC4MRINW-BNmPRFJF.js +10 -0
- package/dist/assets/channel-CiySTNoJ.js +1 -0
- package/dist/assets/chunk-4BX2VUAB-DGQTvirp.js +1 -0
- package/dist/assets/chunk-55IACEB6-DNMAQAC_.js +1 -0
- package/dist/assets/chunk-FMBD7UC4-BJbVTQ5o.js +15 -0
- package/dist/assets/chunk-JSJVCQXG-BCxUL74A.js +1 -0
- package/dist/assets/chunk-KX2RTZJC-H7wWZOfz.js +1 -0
- package/dist/assets/chunk-NQ4KR5QH-BK4RlTQF.js +220 -0
- package/dist/assets/chunk-QZHKN3VN-0chxDV5g.js +1 -0
- package/dist/assets/chunk-WL4C6EOR-DexfQ-AV.js +189 -0
- package/dist/assets/classDiagram-VBA2DB6C-D7luWJQn.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-D7luWJQn.js +1 -0
- package/dist/assets/clone-ylgRbd3D.js +1 -0
- package/dist/assets/cose-bilkent-S5V4N54A-DS2IOCfZ.js +1 -0
- package/dist/assets/cytoscape.esm-CyJtwmzi.js +331 -0
- package/dist/assets/dagre-KLK3FWXG-BbSoTTa3.js +4 -0
- package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/assets/diagram-E7M64L7V-C9TvYgv0.js +24 -0
- package/dist/assets/diagram-IFDJBPK2-DowUMWrg.js +43 -0
- package/dist/assets/diagram-P4PSJMXO-BL6nrnQF.js +24 -0
- package/dist/assets/erDiagram-INFDFZHY-rXPRl8VM.js +70 -0
- package/dist/assets/flowDiagram-PKNHOUZH-DBRM99-W.js +162 -0
- package/dist/assets/ganttDiagram-A5KZAMGK-INcWFsBT.js +292 -0
- package/dist/assets/gitGraphDiagram-K3NZZRJ6-DMwpfE91.js +65 -0
- package/dist/assets/graph-DLQn37b-.js +1 -0
- package/dist/assets/index-BFFITMT8.js +650 -0
- package/dist/assets/index-H7f6VTz1.css +1 -0
- package/dist/assets/infoDiagram-LFFYTUFH-B0f4TWRM.js +2 -0
- package/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dist/assets/ishikawaDiagram-PHBUUO56-CsU6XimZ.js +70 -0
- package/dist/assets/journeyDiagram-4ABVD52K-CQ7ibNib.js +139 -0
- package/dist/assets/kanban-definition-K7BYSVSG-DzEN7THt.js +89 -0
- package/dist/assets/katex-B1X10hvy.js +261 -0
- package/dist/assets/layout-C0dvb42R.js +1 -0
- package/dist/assets/linear-j4a8mGj7.js +1 -0
- package/dist/assets/mindmap-definition-YRQLILUH-DP8iEuCf.js +68 -0
- package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/assets/pieDiagram-SKSYHLDU-BpIAXgAm.js +30 -0
- package/dist/assets/quadrantDiagram-337W2JSQ-DrpXn5Eg.js +7 -0
- package/dist/assets/requirementDiagram-Z7DCOOCP-Bg7EwHlG.js +73 -0
- package/dist/assets/sankeyDiagram-WA2Y5GQK-BWagRs1F.js +10 -0
- package/dist/assets/sequenceDiagram-2WXFIKYE-q5jwhivG.js +145 -0
- package/dist/assets/stateDiagram-RAJIS63D-B_J9pE-2.js +1 -0
- package/dist/assets/stateDiagram-v2-FVOUBMTO-Q_1GcybB.js +1 -0
- package/dist/assets/timeline-definition-YZTLITO2-dv0jgQ0z.js +61 -0
- package/dist/assets/treemap-KZPCXAKY-Dt1dkIE7.js +162 -0
- package/dist/assets/vennDiagram-LZ73GAT5-BdO5RgRZ.js +34 -0
- package/dist/assets/xychartDiagram-JWTSCODW-CpDVe-8v.js +7 -0
- package/dist/index.html +23 -0
- package/export-docx.js +1583 -0
- package/init.js +353 -0
- package/manifest-cli.mjs +207 -0
- package/package.json +83 -0
- package/schemas/artifact.schema.json +1295 -0
- package/schemas/artifact.uischema.json +65 -0
- package/schemas/evaluation.schema.json +284 -0
- package/schemas/rubric.schema.json +383 -0
- package/serve.js +238 -0
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
kind: artifact
|
|
2
|
+
artifact_type: reference_architecture
|
|
3
|
+
|
|
4
|
+
metadata:
|
|
5
|
+
title: Multi-Cloud Data Analytics Platform
|
|
6
|
+
version: 1.0.0
|
|
7
|
+
status: draft
|
|
8
|
+
author: Thomas Rohde
|
|
9
|
+
owner: Enterprise Architecture, Data Platform Domain
|
|
10
|
+
effective_date: "2026-03-21"
|
|
11
|
+
next_review_date: "2026-09-21"
|
|
12
|
+
last_updated: "2026-03-21"
|
|
13
|
+
purpose: >
|
|
14
|
+
This reference architecture defines the target pattern for a multi-cloud data
|
|
15
|
+
analytics platform that combines best-of-breed services from AWS, Azure, and
|
|
16
|
+
Google Cloud. It demonstrates how architecture diagrams can use vendor-specific
|
|
17
|
+
icons to communicate cloud placement clearly, and serves as an example of
|
|
18
|
+
multi-cloud Mermaid diagrams with the EaROS icon system.
|
|
19
|
+
decision_context: >
|
|
20
|
+
Architecture Board review Q1 2026. The enterprise data platform is expanding
|
|
21
|
+
from a single-cloud AWS deployment to a multi-cloud strategy. Primary compute
|
|
22
|
+
and storage remain on AWS. Azure provides enterprise identity and Power BI
|
|
23
|
+
reporting. Google Cloud contributes BigQuery for ad-hoc analytics and Vertex AI
|
|
24
|
+
for ML workloads. This reference architecture governs all new data pipeline
|
|
25
|
+
services.
|
|
26
|
+
stakeholders:
|
|
27
|
+
- role: Executive Sponsor
|
|
28
|
+
name: Chief Data Officer
|
|
29
|
+
concerns: >
|
|
30
|
+
Data strategy alignment, cost distribution across clouds, vendor lock-in
|
|
31
|
+
risk, and time to insight for business analysts.
|
|
32
|
+
- role: Platform Architect
|
|
33
|
+
name: Enterprise Architecture
|
|
34
|
+
concerns: >
|
|
35
|
+
Cross-cloud networking, identity federation, data sovereignty, and
|
|
36
|
+
architectural consistency.
|
|
37
|
+
- role: Data Engineer Lead
|
|
38
|
+
name: Data Platform Engineering
|
|
39
|
+
concerns: >
|
|
40
|
+
Pipeline reliability, schema evolution, backfill procedures, and
|
|
41
|
+
development experience across three clouds.
|
|
42
|
+
- role: Security Architect
|
|
43
|
+
name: Information Security
|
|
44
|
+
concerns: >
|
|
45
|
+
Cross-cloud IAM federation, encryption in transit and at rest across
|
|
46
|
+
boundaries, and audit trail completeness.
|
|
47
|
+
- role: BI Analyst Lead
|
|
48
|
+
name: Business Intelligence
|
|
49
|
+
concerns: >
|
|
50
|
+
Data freshness in dashboards, self-service query access, and Power BI
|
|
51
|
+
workspace governance.
|
|
52
|
+
change_log:
|
|
53
|
+
- version: "1.0.0"
|
|
54
|
+
date: "2026-03-21"
|
|
55
|
+
author: Thomas Rohde
|
|
56
|
+
changes:
|
|
57
|
+
- Initial draft — multi-cloud icon demonstration artifact
|
|
58
|
+
- All 4 architecture views with AWS, Azure, and GCP icons
|
|
59
|
+
- 3 ADRs covering cloud selection, identity federation, and data transfer
|
|
60
|
+
|
|
61
|
+
sections:
|
|
62
|
+
reading_guide:
|
|
63
|
+
how_to_use: >
|
|
64
|
+
This document is structured so each audience can navigate directly to
|
|
65
|
+
their primary concerns. Architecture views use vendor-specific icons
|
|
66
|
+
(AWS orange, Azure blue, GCP coloured) to make cloud placement
|
|
67
|
+
immediately visible in every diagram.
|
|
68
|
+
section_map:
|
|
69
|
+
- section: Business Context
|
|
70
|
+
audience: CDO, Executive Sponsor
|
|
71
|
+
concern: Strategic drivers for multi-cloud and expected outcomes
|
|
72
|
+
- section: Architecture Views — Context
|
|
73
|
+
audience: Platform Architect, Security Architect
|
|
74
|
+
concern: System boundary, cross-cloud actors, and integration points
|
|
75
|
+
- section: Architecture Views — Functional
|
|
76
|
+
audience: Data Engineer Lead, Platform Architect
|
|
77
|
+
concern: Service decomposition across clouds and data flow paths
|
|
78
|
+
- section: Architecture Views — Deployment
|
|
79
|
+
audience: Platform Architect, Security Architect
|
|
80
|
+
concern: Network topology, cross-cloud connectivity, identity federation
|
|
81
|
+
- section: Architecture Views — Data Flow
|
|
82
|
+
audience: Data Engineer Lead, BI Analyst Lead
|
|
83
|
+
concern: Runtime data pipeline from ingestion to dashboard
|
|
84
|
+
- section: Architecture Decisions (ADRs)
|
|
85
|
+
audience: Platform Architect, Security Architect
|
|
86
|
+
concern: Cloud selection rationale, identity federation, cross-cloud transfer
|
|
87
|
+
|
|
88
|
+
scope:
|
|
89
|
+
statement: >
|
|
90
|
+
This reference architecture covers a multi-cloud data analytics platform
|
|
91
|
+
spanning AWS, Azure, and Google Cloud. Data is ingested and stored on AWS,
|
|
92
|
+
transformed via cross-cloud pipelines, analysed on BigQuery (GCP), and
|
|
93
|
+
visualised through Power BI (Azure).
|
|
94
|
+
in_scope:
|
|
95
|
+
- Data ingestion API (AWS API Gateway + Lambda)
|
|
96
|
+
- Raw data lake (AWS S3)
|
|
97
|
+
- Stream processing (AWS Kinesis Data Streams + Firehose)
|
|
98
|
+
- Data warehouse (AWS Redshift) — primary structured storage
|
|
99
|
+
- Cross-cloud data transfer (AWS S3 → GCP Cloud Storage via Storage Transfer Service)
|
|
100
|
+
- Ad-hoc analytics (GCP BigQuery)
|
|
101
|
+
- ML model training and serving (GCP Vertex AI)
|
|
102
|
+
- Enterprise identity federation (Azure Entra ID → AWS IAM + GCP IAM)
|
|
103
|
+
- BI dashboards (Azure Power BI connected to Redshift and BigQuery)
|
|
104
|
+
- Monitoring (AWS CloudWatch, GCP Cloud Monitoring, Azure Monitor — federated via Datadog)
|
|
105
|
+
- Infrastructure as code (Terraform multi-provider)
|
|
106
|
+
out_of_scope:
|
|
107
|
+
- Source system integrations — covered by domain-specific patterns
|
|
108
|
+
- Data governance tooling — separate initiative (Collibra)
|
|
109
|
+
- ML model development workflow — governed by ML platform team
|
|
110
|
+
constraints:
|
|
111
|
+
- All data classified as PII must remain within EU regions across all clouds
|
|
112
|
+
- Cross-cloud network traffic must traverse private interconnects, not public internet
|
|
113
|
+
- Single identity provider (Azure Entra ID) for all human access
|
|
114
|
+
assumptions:
|
|
115
|
+
- assumption: AWS-GCP dedicated interconnect is provisioned in eu-west-1 ↔ europe-west1
|
|
116
|
+
consequence_if_violated: >
|
|
117
|
+
Data transfer between AWS and GCP would fall back to public internet,
|
|
118
|
+
increasing latency, egress costs, and GDPR compliance risk.
|
|
119
|
+
- assumption: Azure ExpressRoute is available in North Europe
|
|
120
|
+
consequence_if_violated: >
|
|
121
|
+
Power BI DirectQuery to Redshift would traverse the public internet,
|
|
122
|
+
degrading dashboard refresh latency and requiring additional encryption
|
|
123
|
+
controls.
|
|
124
|
+
- assumption: All three cloud accounts are under enterprise agreements with committed spend
|
|
125
|
+
consequence_if_violated: >
|
|
126
|
+
On-demand pricing across three clouds would significantly increase costs,
|
|
127
|
+
potentially undermining the financial case for multi-cloud.
|
|
128
|
+
|
|
129
|
+
business_context:
|
|
130
|
+
business_drivers:
|
|
131
|
+
- driver: Best-of-breed analytics
|
|
132
|
+
description: >
|
|
133
|
+
BigQuery provides the most cost-effective serverless analytics for
|
|
134
|
+
ad-hoc exploration. Power BI is the enterprise standard for executive
|
|
135
|
+
dashboards. Combining both gives analysts the right tool for each task.
|
|
136
|
+
- driver: Vendor diversification
|
|
137
|
+
description: >
|
|
138
|
+
Board directive to reduce single-vendor dependency below 80% of cloud
|
|
139
|
+
spend by 2027. This architecture distributes workloads across three
|
|
140
|
+
providers.
|
|
141
|
+
- driver: ML capability
|
|
142
|
+
description: >
|
|
143
|
+
Vertex AI offers managed ML pipelines and model serving that
|
|
144
|
+
complement the existing AWS data infrastructure without re-platforming
|
|
145
|
+
the data lake.
|
|
146
|
+
use_cases:
|
|
147
|
+
- name: Real-time order analytics
|
|
148
|
+
description: >
|
|
149
|
+
Stream order events from the e-commerce platform through Kinesis into
|
|
150
|
+
Redshift and BigQuery for real-time dashboards and ad-hoc analysis.
|
|
151
|
+
- name: Executive reporting
|
|
152
|
+
description: >
|
|
153
|
+
Power BI connects to both Redshift (operational metrics) and BigQuery
|
|
154
|
+
(ad-hoc analysis) to provide unified executive dashboards with
|
|
155
|
+
scheduled refresh.
|
|
156
|
+
- name: Demand forecasting
|
|
157
|
+
description: >
|
|
158
|
+
Historical order data is transferred to GCP, where Vertex AI trains
|
|
159
|
+
demand forecasting models. Predictions are written back to Redshift
|
|
160
|
+
for operational use.
|
|
161
|
+
|
|
162
|
+
architecture_views:
|
|
163
|
+
context:
|
|
164
|
+
description: >
|
|
165
|
+
The context view shows the multi-cloud analytics platform boundary and
|
|
166
|
+
its relationships with external actors across three cloud providers.
|
|
167
|
+
AWS hosts the core data platform (ingestion, storage, warehouse). GCP
|
|
168
|
+
provides BigQuery for analytics and Vertex AI for ML. Azure provides
|
|
169
|
+
enterprise identity (Entra ID) and reporting (Power BI).
|
|
170
|
+
key_decisions:
|
|
171
|
+
- AWS is the primary data platform — all raw data lands here first
|
|
172
|
+
- GCP receives curated datasets via dedicated interconnect for analytics
|
|
173
|
+
- Azure Entra ID is the single identity provider for all human access
|
|
174
|
+
- Cross-cloud data transfer uses private interconnects, never public internet
|
|
175
|
+
diagram_source: |
|
|
176
|
+
flowchart LR
|
|
177
|
+
classDef actor fill:#f8fafc,stroke:#334155,stroke-width:1.4px,color:#0f172a;
|
|
178
|
+
classDef external fill:#fff7ed,stroke:#c2410c,stroke-width:1.4px,color:#7c2d12;
|
|
179
|
+
|
|
180
|
+
Analyst@{ shape: stadium, label: "Business Analyst" }
|
|
181
|
+
DataEng@{ shape: stadium, label: "Data Engineer" }
|
|
182
|
+
MLEng@{ shape: stadium, label: "ML Engineer" }
|
|
183
|
+
SourceSys@{ shape: cloud, label: "Source Systems\n(ERP, CRM, E-Commerce)" }
|
|
184
|
+
|
|
185
|
+
subgraph AWS["AWS (Primary Data Platform)"]
|
|
186
|
+
APIGW@{ img: "/icons/aws/api-gateway.svg", label: "API Gateway", pos: "b", w: 52, h: 52, constraint: "on" }
|
|
187
|
+
S3@{ img: "/icons/aws/s3.svg", label: "Data Lake\n(S3)", pos: "b", w: 52, h: 52, constraint: "on" }
|
|
188
|
+
Redshift@{ img: "/icons/aws/redshift.svg", label: "Redshift\nWarehouse", pos: "b", w: 52, h: 52, constraint: "on" }
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
subgraph GCP["Google Cloud (Analytics & ML)"]
|
|
192
|
+
BigQuery@{ img: "/icons/gcp/bigquery.svg", label: "BigQuery", pos: "b", w: 52, h: 52, constraint: "on" }
|
|
193
|
+
VertexAI@{ img: "/icons/gcp/cloud-run.svg", label: "Vertex AI", pos: "b", w: 52, h: 52, constraint: "on" }
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
subgraph Azure["Azure (Identity & Reporting)"]
|
|
197
|
+
EntraID@{ img: "/icons/azure/entra-id.svg", label: "Entra ID", pos: "b", w: 52, h: 52, constraint: "on" }
|
|
198
|
+
PowerBI@{ img: "/icons/azure/synapse-analytics.svg", label: "Power BI", pos: "b", w: 52, h: 52, constraint: "on" }
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
SourceSys -->|Events & CDC| APIGW
|
|
202
|
+
APIGW --> S3
|
|
203
|
+
S3 --> Redshift
|
|
204
|
+
S3 -.->|Interconnect| BigQuery
|
|
205
|
+
BigQuery --> VertexAI
|
|
206
|
+
VertexAI -.->|Predictions| Redshift
|
|
207
|
+
|
|
208
|
+
EntraID -->|Federation| AWS
|
|
209
|
+
EntraID -->|Federation| GCP
|
|
210
|
+
Analyst --> PowerBI
|
|
211
|
+
PowerBI --> Redshift
|
|
212
|
+
PowerBI --> BigQuery
|
|
213
|
+
DataEng --> Redshift
|
|
214
|
+
MLEng --> VertexAI
|
|
215
|
+
|
|
216
|
+
class Analyst,DataEng,MLEng actor
|
|
217
|
+
class SourceSys external
|
|
218
|
+
source_type: mermaid
|
|
219
|
+
|
|
220
|
+
functional:
|
|
221
|
+
description: >
|
|
222
|
+
The functional view decomposes the platform into its constituent services
|
|
223
|
+
across all three clouds. Each node is annotated with its cloud provider
|
|
224
|
+
icon to make placement unambiguous. Data flows left to right: ingest on
|
|
225
|
+
AWS, transform on AWS, transfer to GCP for analytics, and report via
|
|
226
|
+
Azure Power BI.
|
|
227
|
+
components:
|
|
228
|
+
- name: Ingestion API
|
|
229
|
+
cloud: AWS
|
|
230
|
+
service: API Gateway + Lambda
|
|
231
|
+
responsibility: >
|
|
232
|
+
Accept events from source systems via REST/webhook. Validate schema,
|
|
233
|
+
enrich with metadata, write to Kinesis.
|
|
234
|
+
- name: Stream Processor
|
|
235
|
+
cloud: AWS
|
|
236
|
+
service: Kinesis Data Streams + Firehose
|
|
237
|
+
responsibility: >
|
|
238
|
+
Buffer and deliver raw events to S3 data lake. Apply basic filtering
|
|
239
|
+
and partitioning by event type and date.
|
|
240
|
+
- name: Data Lake
|
|
241
|
+
cloud: AWS
|
|
242
|
+
service: S3 (Iceberg tables)
|
|
243
|
+
responsibility: >
|
|
244
|
+
Store raw and curated data in open table format. Serve as the
|
|
245
|
+
single source of truth for all downstream consumers.
|
|
246
|
+
- name: Data Warehouse
|
|
247
|
+
cloud: AWS
|
|
248
|
+
service: Redshift Serverless
|
|
249
|
+
responsibility: >
|
|
250
|
+
Provide structured, optimised storage for operational analytics.
|
|
251
|
+
Serve as primary data source for Power BI dashboards.
|
|
252
|
+
- name: Transfer Service
|
|
253
|
+
cloud: GCP
|
|
254
|
+
service: Storage Transfer Service
|
|
255
|
+
responsibility: >
|
|
256
|
+
Scheduled and event-triggered transfer of curated datasets from
|
|
257
|
+
AWS S3 to GCP Cloud Storage via dedicated interconnect.
|
|
258
|
+
- name: Analytics Engine
|
|
259
|
+
cloud: GCP
|
|
260
|
+
service: BigQuery
|
|
261
|
+
responsibility: >
|
|
262
|
+
Serverless SQL analytics on curated datasets. Ad-hoc exploration
|
|
263
|
+
by analysts. Serve as secondary data source for Power BI.
|
|
264
|
+
- name: ML Platform
|
|
265
|
+
cloud: GCP
|
|
266
|
+
service: Vertex AI
|
|
267
|
+
responsibility: >
|
|
268
|
+
Train and serve ML models (demand forecasting, anomaly detection).
|
|
269
|
+
Read from BigQuery, write predictions back to Redshift.
|
|
270
|
+
- name: Identity Provider
|
|
271
|
+
cloud: Azure
|
|
272
|
+
service: Entra ID
|
|
273
|
+
responsibility: >
|
|
274
|
+
Single source of truth for human identity. Federate to AWS IAM
|
|
275
|
+
Identity Center and GCP Workforce Identity Federation.
|
|
276
|
+
- name: Reporting
|
|
277
|
+
cloud: Azure
|
|
278
|
+
service: Power BI Premium
|
|
279
|
+
responsibility: >
|
|
280
|
+
Enterprise dashboards connecting to Redshift (DirectQuery) and
|
|
281
|
+
BigQuery (Import with scheduled refresh).
|
|
282
|
+
diagram_source: |
|
|
283
|
+
flowchart LR
|
|
284
|
+
classDef external fill:#fff7ed,stroke:#c2410c,stroke-width:1.4px,color:#7c2d12;
|
|
285
|
+
|
|
286
|
+
Sources@{ shape: cloud, label: "Source\nSystems" }
|
|
287
|
+
|
|
288
|
+
subgraph AWS["AWS — Ingest & Store"]
|
|
289
|
+
direction TB
|
|
290
|
+
APIGW@{ img: "/icons/aws/api-gateway.svg", label: "API Gateway", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
291
|
+
Lambda@{ img: "/icons/aws/lambda.svg", label: "Ingestion\nLambda", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
292
|
+
Kinesis@{ img: "/icons/aws/kinesis.svg", label: "Kinesis Data\nStreams", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
293
|
+
Firehose@{ img: "/icons/aws/data-firehose.svg", label: "Firehose", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
294
|
+
S3@{ img: "/icons/aws/s3.svg", label: "S3 Data Lake\n(Iceberg)", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
295
|
+
Redshift@{ img: "/icons/aws/redshift.svg", label: "Redshift\nServerless", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
296
|
+
CW@{ img: "/icons/aws/cloudwatch.svg", label: "CloudWatch", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
297
|
+
|
|
298
|
+
APIGW --> Lambda --> Kinesis --> Firehose --> S3
|
|
299
|
+
S3 --> Redshift
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
subgraph GCP["GCP — Analyse & Predict"]
|
|
303
|
+
direction TB
|
|
304
|
+
GCS@{ img: "/icons/gcp/cloud-storage.svg", label: "Cloud Storage\n(Landing)", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
305
|
+
BQ@{ img: "/icons/gcp/bigquery.svg", label: "BigQuery", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
306
|
+
Vertex@{ img: "/icons/gcp/cloud-run.svg", label: "Vertex AI", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
307
|
+
GCM@{ img: "/icons/gcp/cloud-monitoring.svg", label: "Cloud\nMonitoring", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
308
|
+
|
|
309
|
+
GCS --> BQ --> Vertex
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
subgraph Azure["Azure — Identity & Report"]
|
|
313
|
+
direction TB
|
|
314
|
+
Entra@{ img: "/icons/azure/entra-id.svg", label: "Entra ID", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
315
|
+
PBI@{ img: "/icons/azure/synapse-analytics.svg", label: "Power BI\nPremium", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
316
|
+
Monitor@{ img: "/icons/azure/monitor.svg", label: "Azure\nMonitor", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
Sources --> APIGW
|
|
320
|
+
S3 -.->|Dedicated interconnect| GCS
|
|
321
|
+
Vertex -.->|Predictions| Redshift
|
|
322
|
+
Redshift --> PBI
|
|
323
|
+
BQ --> PBI
|
|
324
|
+
Entra -->|SAML/OIDC| AWS
|
|
325
|
+
Entra -->|Workforce IdP| GCP
|
|
326
|
+
|
|
327
|
+
class Sources external
|
|
328
|
+
source_type: mermaid
|
|
329
|
+
|
|
330
|
+
deployment:
|
|
331
|
+
description: >
|
|
332
|
+
The deployment view shows the network topology across all three cloud
|
|
333
|
+
providers. Each cloud has its own VPC/VNet/VPC and they are connected
|
|
334
|
+
via dedicated interconnects (AWS Direct Connect to GCP, Azure
|
|
335
|
+
ExpressRoute). All data transfer crosses private links — never the
|
|
336
|
+
public internet.
|
|
337
|
+
key_decisions:
|
|
338
|
+
- Private interconnects between all three clouds via Megaport fabric
|
|
339
|
+
- Each cloud uses private subnets only — no public endpoints for data services
|
|
340
|
+
- DNS resolution via Route 53 with forwarding rules to Azure Private DNS and GCP Cloud DNS
|
|
341
|
+
- TLS 1.3 enforced on all cross-cloud data transfers
|
|
342
|
+
diagram_source: |
|
|
343
|
+
flowchart TB
|
|
344
|
+
Route53@{ img: "/icons/aws/route53.svg", label: "Route 53\nCentral DNS", pos: "b", w: 52, h: 52, constraint: "on" }
|
|
345
|
+
|
|
346
|
+
subgraph AWS_Region["AWS eu-west-1"]
|
|
347
|
+
direction TB
|
|
348
|
+
WAF@{ img: "/icons/aws/waf.svg", label: "WAF", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
349
|
+
APIGW@{ img: "/icons/aws/api-gateway.svg", label: "API Gateway", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
350
|
+
|
|
351
|
+
subgraph AWS_VPC["VPC 10.0.0.0/16"]
|
|
352
|
+
direction LR
|
|
353
|
+
subgraph AWS_Private["Private Subnets"]
|
|
354
|
+
direction TB
|
|
355
|
+
Lambda@{ img: "/icons/aws/lambda.svg", label: "Lambda\nFunctions", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
356
|
+
Kinesis@{ img: "/icons/aws/kinesis.svg", label: "Kinesis", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
357
|
+
S3@{ img: "/icons/aws/s3.svg", label: "S3 Data Lake", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
358
|
+
Redshift@{ img: "/icons/aws/redshift.svg", label: "Redshift", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
WAF --> APIGW --> Lambda
|
|
363
|
+
Lambda --> Kinesis --> S3
|
|
364
|
+
S3 --> Redshift
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
subgraph GCP_Region["GCP europe-west1"]
|
|
368
|
+
direction TB
|
|
369
|
+
Armor@{ img: "/icons/gcp/cloud-armor.svg", label: "Cloud Armor", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
370
|
+
|
|
371
|
+
subgraph GCP_VPC["VPC 10.1.0.0/16"]
|
|
372
|
+
direction TB
|
|
373
|
+
GCS@{ img: "/icons/gcp/cloud-storage.svg", label: "Cloud Storage", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
374
|
+
BQ@{ img: "/icons/gcp/bigquery.svg", label: "BigQuery", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
375
|
+
Vertex@{ img: "/icons/gcp/cloud-run.svg", label: "Vertex AI", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
GCS --> BQ --> Vertex
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
subgraph Azure_Region["Azure North Europe"]
|
|
382
|
+
direction TB
|
|
383
|
+
FrontDoor@{ img: "/icons/azure/front-door.svg", label: "Front Door", pos: "b", w: 48, h: 48, constraint: "on" }
|
|
384
|
+
|
|
385
|
+
subgraph Azure_VNet["VNet 10.2.0.0/16"]
|
|
386
|
+
direction TB
|
|
387
|
+
Entra@{ img: "/icons/azure/entra-id.svg", label: "Entra ID", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
388
|
+
PBI@{ img: "/icons/azure/synapse-analytics.svg", label: "Power BI\nGateway", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
Route53 --> AWS_Region
|
|
393
|
+
Route53 -.-> GCP_Region
|
|
394
|
+
Route53 -.-> Azure_Region
|
|
395
|
+
|
|
396
|
+
S3 ===|"AWS Direct Connect\nto GCP Interconnect\n(Megaport)"| GCS
|
|
397
|
+
Redshift ===|"ExpressRoute\n(Megaport)"| PBI
|
|
398
|
+
BQ ===|"GCP Interconnect\nto ExpressRoute"| PBI
|
|
399
|
+
Entra -->|"SAML federation"| APIGW
|
|
400
|
+
Entra -->|"Workforce IdP"| Armor
|
|
401
|
+
Vertex -.->|"Predictions via\ninterconnect"| Redshift
|
|
402
|
+
source_type: mermaid
|
|
403
|
+
|
|
404
|
+
data_flow:
|
|
405
|
+
description: >
|
|
406
|
+
The data flow view traces the lifecycle of an order event from source
|
|
407
|
+
system ingestion through transformation, cross-cloud transfer, analytics,
|
|
408
|
+
ML inference, and finally executive reporting. Each step is numbered
|
|
409
|
+
and annotated with the cloud provider and service responsible.
|
|
410
|
+
narrative_steps:
|
|
411
|
+
- step: 1
|
|
412
|
+
description: >
|
|
413
|
+
Source systems (ERP, e-commerce) push order events to the AWS API
|
|
414
|
+
Gateway via REST webhooks. Lambda validates the schema and enriches
|
|
415
|
+
events with ingestion metadata.
|
|
416
|
+
- step: 2
|
|
417
|
+
description: >
|
|
418
|
+
Validated events are written to Kinesis Data Streams for real-time
|
|
419
|
+
buffering. Kinesis Data Firehose delivers micro-batches to S3 in
|
|
420
|
+
Parquet format, partitioned by date and event type.
|
|
421
|
+
- step: 3
|
|
422
|
+
description: >
|
|
423
|
+
AWS Glue crawlers register new partitions in the Iceberg catalog.
|
|
424
|
+
Redshift Spectrum queries the data lake directly; Redshift Serverless
|
|
425
|
+
loads curated tables for dashboard queries.
|
|
426
|
+
- step: 4
|
|
427
|
+
description: >
|
|
428
|
+
GCP Storage Transfer Service copies curated Parquet files from S3 to
|
|
429
|
+
Cloud Storage on a 15-minute schedule via dedicated interconnect. No
|
|
430
|
+
data traverses the public internet.
|
|
431
|
+
- step: 5
|
|
432
|
+
description: >
|
|
433
|
+
BigQuery external tables point at the Cloud Storage landing zone.
|
|
434
|
+
Analysts run ad-hoc SQL queries directly in BigQuery. Vertex AI
|
|
435
|
+
training jobs read from BigQuery.
|
|
436
|
+
- step: 6
|
|
437
|
+
description: >
|
|
438
|
+
Vertex AI trains demand forecasting models nightly. Batch predictions
|
|
439
|
+
are written to a BigQuery results table, then pushed back to Redshift
|
|
440
|
+
via the interconnect for operational consumption.
|
|
441
|
+
- step: 7
|
|
442
|
+
description: >
|
|
443
|
+
Power BI Premium connects to Redshift via DirectQuery for real-time
|
|
444
|
+
operational dashboards and to BigQuery via Import with 30-minute
|
|
445
|
+
scheduled refresh for analytical dashboards.
|
|
446
|
+
diagram_source: |
|
|
447
|
+
flowchart LR
|
|
448
|
+
classDef step fill:#f0fdf4,stroke:#16a34a,stroke-width:1.2px,color:#14532d;
|
|
449
|
+
|
|
450
|
+
S1["① Ingest"]
|
|
451
|
+
S2["② Buffer"]
|
|
452
|
+
S3_step["③ Store"]
|
|
453
|
+
S4["④ Transfer"]
|
|
454
|
+
S5["⑤ Analyse"]
|
|
455
|
+
S6["⑥ Predict"]
|
|
456
|
+
S7["⑦ Report"]
|
|
457
|
+
|
|
458
|
+
APIGW@{ img: "/icons/aws/api-gateway.svg", label: "API Gateway", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
459
|
+
Lambda@{ img: "/icons/aws/lambda.svg", label: "Lambda", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
460
|
+
Kinesis@{ img: "/icons/aws/kinesis.svg", label: "Kinesis", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
461
|
+
Firehose@{ img: "/icons/aws/data-firehose.svg", label: "Firehose", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
462
|
+
S3@{ img: "/icons/aws/s3.svg", label: "S3", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
463
|
+
Redshift@{ img: "/icons/aws/redshift.svg", label: "Redshift", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
464
|
+
GCS@{ img: "/icons/gcp/cloud-storage.svg", label: "Cloud Storage", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
465
|
+
BQ@{ img: "/icons/gcp/bigquery.svg", label: "BigQuery", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
466
|
+
Vertex@{ img: "/icons/gcp/cloud-run.svg", label: "Vertex AI", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
467
|
+
PBI@{ img: "/icons/azure/synapse-analytics.svg", label: "Power BI", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
468
|
+
Entra@{ img: "/icons/azure/entra-id.svg", label: "Entra ID", pos: "b", w: 44, h: 44, constraint: "on" }
|
|
469
|
+
|
|
470
|
+
S1 --- APIGW --> Lambda
|
|
471
|
+
S2 --- Kinesis --> Firehose
|
|
472
|
+
S3_step --- S3 --> Redshift
|
|
473
|
+
S4 --- GCS
|
|
474
|
+
S5 --- BQ
|
|
475
|
+
S6 --- Vertex
|
|
476
|
+
S7 --- PBI
|
|
477
|
+
|
|
478
|
+
Lambda --> Kinesis
|
|
479
|
+
Firehose --> S3
|
|
480
|
+
S3 -.->|Interconnect| GCS
|
|
481
|
+
GCS --> BQ --> Vertex
|
|
482
|
+
Vertex -.->|Predictions| Redshift
|
|
483
|
+
Redshift --> PBI
|
|
484
|
+
BQ --> PBI
|
|
485
|
+
Entra -.->|SSO| PBI
|
|
486
|
+
|
|
487
|
+
class S1,S2,S3_step,S4,S5,S6,S7 step
|
|
488
|
+
source_type: mermaid
|
|
489
|
+
|
|
490
|
+
decisions:
|
|
491
|
+
- id: ADR-001
|
|
492
|
+
title: Multi-cloud strategy — best-of-breed over single-vendor
|
|
493
|
+
status: accepted
|
|
494
|
+
date: "2026-01-15"
|
|
495
|
+
context: >
|
|
496
|
+
The enterprise data platform has grown on AWS but the board has mandated
|
|
497
|
+
vendor diversification. Business analysts strongly prefer BigQuery for
|
|
498
|
+
ad-hoc analytics and Power BI for executive dashboards. Keeping
|
|
499
|
+
everything on AWS would mean Athena for analytics (less preferred by
|
|
500
|
+
analysts) and QuickSight for BI (not adopted by the enterprise).
|
|
501
|
+
options:
|
|
502
|
+
- id: A
|
|
503
|
+
description: "AWS-only: Use Athena + QuickSight, stay single-cloud"
|
|
504
|
+
pros: [Simpler networking, single IAM, lower operational overhead]
|
|
505
|
+
cons: [Does not meet diversification mandate, analyst resistance to QuickSight]
|
|
506
|
+
- id: B
|
|
507
|
+
description: "AWS + GCP (BigQuery only): Add BigQuery for analytics, keep BI on QuickSight"
|
|
508
|
+
pros: [Addresses analyst preference, partial diversification]
|
|
509
|
+
cons: [Still single BI tool, analysts want Power BI]
|
|
510
|
+
- id: C
|
|
511
|
+
description: "AWS + Azure + GCP: best-of-breed per domain for ingest/storage, analytics/ML, and identity/BI"
|
|
512
|
+
pros: [Best-of-breed per domain, meets diversification mandate, aligns with enterprise BI standard]
|
|
513
|
+
cons: [Cross-cloud networking complexity, three IAM systems to federate, higher operational cost]
|
|
514
|
+
decision: >
|
|
515
|
+
Option 3 (AWS + Azure + GCP). The diversification mandate is non-negotiable.
|
|
516
|
+
BigQuery and Power BI are already enterprise standards in their respective
|
|
517
|
+
domains. The complexity cost is manageable with dedicated interconnects and
|
|
518
|
+
federated identity.
|
|
519
|
+
rationale: >
|
|
520
|
+
The board diversification mandate eliminates Option 1. Option 2 still
|
|
521
|
+
leaves BI on an unadopted tool (QuickSight). Option 3 places each
|
|
522
|
+
workload on the strongest platform for its domain: AWS for data
|
|
523
|
+
infrastructure (established), GCP for analytics (BigQuery leader),
|
|
524
|
+
Azure for identity and BI (enterprise standard). The additional
|
|
525
|
+
operational complexity is bounded by Megaport interconnects and
|
|
526
|
+
federated identity — both well-understood patterns.
|
|
527
|
+
tradeoffs: >
|
|
528
|
+
Accepted: cross-cloud networking complexity, three IAM systems requiring
|
|
529
|
+
federation, higher operational cost, and data transfer latency between
|
|
530
|
+
clouds. Rejected: single-vendor simplicity, unified IAM, and lower
|
|
531
|
+
operational overhead.
|
|
532
|
+
consequences: >
|
|
533
|
+
Three cloud networking fabrics must be connected via Megaport. Identity
|
|
534
|
+
federation from Entra ID to AWS and GCP is mandatory. Data transfer costs
|
|
535
|
+
between clouds must be budgeted and monitored. Operations team needs
|
|
536
|
+
cross-cloud monitoring (Datadog).
|
|
537
|
+
revisit_conditions: >
|
|
538
|
+
If cross-cloud data transfer costs exceed 15% of total cloud spend. If
|
|
539
|
+
Megaport interconnect SLA drops below 99.95%. If any cloud provider
|
|
540
|
+
releases a service that eliminates the best-of-breed advantage.
|
|
541
|
+
|
|
542
|
+
- id: ADR-002
|
|
543
|
+
title: Azure Entra ID as the single identity provider
|
|
544
|
+
status: accepted
|
|
545
|
+
date: "2026-01-22"
|
|
546
|
+
context: >
|
|
547
|
+
With three clouds, each having its own IAM system, human access must be
|
|
548
|
+
federated through a single identity provider. The enterprise already uses
|
|
549
|
+
Azure Entra ID (formerly Azure AD) for all corporate identity. AWS IAM
|
|
550
|
+
Identity Center and GCP Workforce Identity Federation both support SAML/OIDC
|
|
551
|
+
federation from external IdPs.
|
|
552
|
+
options:
|
|
553
|
+
- id: A
|
|
554
|
+
description: "Per-cloud native IAM: manage users separately in each cloud"
|
|
555
|
+
pros: [No cross-cloud dependency]
|
|
556
|
+
cons: [Identity sprawl, inconsistent MFA, audit nightmare]
|
|
557
|
+
- id: B
|
|
558
|
+
description: "Azure Entra ID federation: Entra ID as IdP, federate to AWS and GCP"
|
|
559
|
+
pros: [Single MFA policy, unified audit log, existing enterprise adoption]
|
|
560
|
+
cons: [Azure dependency for all access, federation setup complexity]
|
|
561
|
+
- id: C
|
|
562
|
+
description: "Okta as external IdP: federate to all three clouds via Okta"
|
|
563
|
+
pros: [Cloud-neutral IdP, strong SCIM support]
|
|
564
|
+
cons: [Additional vendor cost, migration from existing Entra ID]
|
|
565
|
+
decision: >
|
|
566
|
+
Azure Entra ID federation. It is the existing enterprise standard, already
|
|
567
|
+
has MFA and Conditional Access policies configured, and both AWS and GCP
|
|
568
|
+
support it natively.
|
|
569
|
+
rationale: >
|
|
570
|
+
Entra ID is already the enterprise identity provider with MFA and
|
|
571
|
+
Conditional Access policies in place. Both AWS (IAM Identity Center)
|
|
572
|
+
and GCP (Workforce Identity Federation) natively support SAML/OIDC
|
|
573
|
+
federation from Entra ID. Using Okta would require migrating from
|
|
574
|
+
the existing IdP and adding vendor cost with no functional advantage.
|
|
575
|
+
Per-cloud IAM would create identity sprawl and audit gaps.
|
|
576
|
+
tradeoffs: >
|
|
577
|
+
Accepted: dependency on Azure for all access across all three clouds;
|
|
578
|
+
federation configuration complexity. Rejected: per-cloud IAM
|
|
579
|
+
simplicity; Okta's cloud-neutral positioning.
|
|
580
|
+
consequences: >
|
|
581
|
+
AWS IAM Identity Center configured with Entra ID as external SAML IdP.
|
|
582
|
+
GCP Workforce Identity Federation configured with Entra ID OIDC.
|
|
583
|
+
Break-glass accounts maintained in each cloud's native IAM for emergency
|
|
584
|
+
access. Conditional Access policies extended to cover BigQuery and
|
|
585
|
+
Redshift access.
|
|
586
|
+
revisit_conditions: >
|
|
587
|
+
If the enterprise migrates away from Microsoft 365. If Entra ID
|
|
588
|
+
federation latency exceeds 500ms p99.
|
|
589
|
+
|
|
590
|
+
- id: ADR-003
|
|
591
|
+
title: Dedicated interconnects over VPN for cross-cloud data transfer
|
|
592
|
+
status: accepted
|
|
593
|
+
date: "2026-02-05"
|
|
594
|
+
context: >
|
|
595
|
+
The platform transfers up to 500 GB/day from AWS S3 to GCP Cloud Storage
|
|
596
|
+
and 50 GB/day of query results between Redshift and Power BI. Data
|
|
597
|
+
includes PII subject to GDPR. Transfer must be private, reliable, and
|
|
598
|
+
cost-effective at scale.
|
|
599
|
+
options:
|
|
600
|
+
- id: A
|
|
601
|
+
description: "Public internet with TLS: transfer over the internet with encryption"
|
|
602
|
+
pros: [No setup cost, works immediately]
|
|
603
|
+
cons: [Variable latency, GDPR risk perception, egress costs at scale]
|
|
604
|
+
- id: B
|
|
605
|
+
description: "Cloud-native VPN tunnels: site-to-site VPN between cloud VPCs"
|
|
606
|
+
pros: [Private routing, moderate setup effort]
|
|
607
|
+
cons: [Throughput limited to ~1.25 Gbps per tunnel, VPN management overhead]
|
|
608
|
+
- id: C
|
|
609
|
+
description: "Dedicated interconnects via Megaport: private cross-connects through colocation fabric"
|
|
610
|
+
pros: [Consistent low latency, 10 Gbps capacity, private routing, no egress surcharge on interconnect]
|
|
611
|
+
cons: [Monthly port and cross-connect fees (~$2,500/month), physical dependency on Megaport PoPs]
|
|
612
|
+
decision: >
|
|
613
|
+
Dedicated interconnects via Megaport. At 500 GB/day, the interconnect
|
|
614
|
+
cost is lower than public internet egress fees. Private routing satisfies
|
|
615
|
+
GDPR data sovereignty requirements without debate.
|
|
616
|
+
rationale: >
|
|
617
|
+
At 500 GB/day transfer volume, dedicated interconnect egress is cheaper
|
|
618
|
+
than public internet egress. Private routing eliminates GDPR data
|
|
619
|
+
sovereignty concerns entirely — no data leaves the Megaport fabric.
|
|
620
|
+
VPN tunnels cap at ~1.25 Gbps per tunnel and require more management.
|
|
621
|
+
Public internet is unsuitable for PII-classified data transfers at
|
|
622
|
+
this scale.
|
|
623
|
+
tradeoffs: >
|
|
624
|
+
Accepted: monthly port and cross-connect fees (~$2,500/month); physical
|
|
625
|
+
dependency on Megaport PoPs in Dublin and Frankfurt; 4-6 week lead time
|
|
626
|
+
for provisioning. Rejected: zero-cost public internet option; simpler
|
|
627
|
+
VPN tunnel setup.
|
|
628
|
+
consequences: >
|
|
629
|
+
Megaport ports provisioned in Dublin (AWS eu-west-1), Frankfurt (GCP
|
|
630
|
+
europe-west1), and Dublin (Azure North Europe). BGP routing configured
|
|
631
|
+
between all three clouds. Failover to VPN tunnels if interconnect goes
|
|
632
|
+
down. Monthly interconnect cost added to platform budget.
|
|
633
|
+
revisit_conditions: >
|
|
634
|
+
If daily transfer volume drops below 50 GB (VPN becomes more
|
|
635
|
+
cost-effective). If any cloud provider offers native multi-cloud
|
|
636
|
+
private connectivity.
|
|
637
|
+
|
|
638
|
+
quality_attributes:
|
|
639
|
+
- attribute: Data freshness
|
|
640
|
+
target: "Raw events available in S3 within 5 minutes of ingestion; curated data in BigQuery within 30 minutes"
|
|
641
|
+
validation: Kinesis iterator age alarm + BigQuery partition freshness query
|
|
642
|
+
- attribute: Query performance
|
|
643
|
+
target: "P95 BigQuery ad-hoc queries complete within 30 seconds on datasets up to 10 TB"
|
|
644
|
+
validation: BigQuery INFORMATION_SCHEMA.JOBS monitoring
|
|
645
|
+
- attribute: Dashboard refresh
|
|
646
|
+
target: "Power BI DirectQuery dashboards reflect Redshift data within 60 seconds; Import datasets refresh every 30 minutes"
|
|
647
|
+
validation: Power BI refresh monitoring + Redshift query log
|
|
648
|
+
- attribute: Cross-cloud transfer reliability
|
|
649
|
+
target: "99.9% success rate for S3 → GCS transfer jobs, zero data loss"
|
|
650
|
+
validation: Storage Transfer Service job completion monitoring + row count reconciliation
|
|
651
|
+
- attribute: Identity federation latency
|
|
652
|
+
target: "SSO login to any cloud console completes within 3 seconds p99"
|
|
653
|
+
validation: Entra ID sign-in logs + synthetic monitoring
|
|
654
|
+
|
|
655
|
+
raid_log:
|
|
656
|
+
risks:
|
|
657
|
+
- id: R-001
|
|
658
|
+
description: >
|
|
659
|
+
Cross-cloud interconnect failure could halt data transfer to GCP,
|
|
660
|
+
degrading BigQuery freshness and ML model retraining.
|
|
661
|
+
likelihood: low
|
|
662
|
+
impact: high
|
|
663
|
+
mitigation: >
|
|
664
|
+
Automated failover to VPN tunnels. Storage Transfer Service retries
|
|
665
|
+
automatically. BigQuery queries degrade gracefully to stale data.
|
|
666
|
+
- id: R-002
|
|
667
|
+
description: >
|
|
668
|
+
Azure Entra ID outage blocks human access to all three clouds
|
|
669
|
+
simultaneously.
|
|
670
|
+
likelihood: very_low
|
|
671
|
+
impact: critical
|
|
672
|
+
mitigation: >
|
|
673
|
+
Break-glass accounts in each cloud's native IAM. Tested quarterly.
|
|
674
|
+
Entra ID SLA is 99.99%.
|
|
675
|
+
- id: R-003
|
|
676
|
+
description: >
|
|
677
|
+
Cross-cloud data transfer costs exceed budget as data volume grows.
|
|
678
|
+
likelihood: medium
|
|
679
|
+
impact: medium
|
|
680
|
+
mitigation: >
|
|
681
|
+
Monthly cost monitoring with 80% budget alerts. Data lifecycle
|
|
682
|
+
policies delete aged data from GCS after BigQuery ingestion. ADR-003
|
|
683
|
+
revisit trigger at 15% of total spend.
|
|
684
|
+
assumptions:
|
|
685
|
+
- id: A-001
|
|
686
|
+
description: >
|
|
687
|
+
Source systems can push events to a REST endpoint. Systems that cannot
|
|
688
|
+
are out of scope for this reference architecture.
|
|
689
|
+
- id: A-002
|
|
690
|
+
description: >
|
|
691
|
+
All three cloud enterprise agreements include committed spend that
|
|
692
|
+
makes multi-cloud cost-effective versus on-demand pricing.
|
|
693
|
+
dependencies:
|
|
694
|
+
- id: D-001
|
|
695
|
+
description: >
|
|
696
|
+
Megaport interconnect provisioning in Dublin and Frankfurt — lead time
|
|
697
|
+
approximately 4-6 weeks.
|
|
698
|
+
- id: D-002
|
|
699
|
+
description: >
|
|
700
|
+
GCP Workforce Identity Federation with Entra ID — requires GCP
|
|
701
|
+
organisation admin approval.
|
|
702
|
+
|
|
703
|
+
governance:
|
|
704
|
+
review_cadence: Quarterly architecture review with all three cloud teams
|
|
705
|
+
exception_process: >
|
|
706
|
+
Any deviation from the prescribed cross-cloud data transfer patterns
|
|
707
|
+
requires Architecture Board approval and a documented exception in the
|
|
708
|
+
RAID log.
|
|
709
|
+
compliance_frameworks:
|
|
710
|
+
- name: GDPR
|
|
711
|
+
mapping: >
|
|
712
|
+
All PII data remains in EU regions. Cross-cloud transfers use private
|
|
713
|
+
interconnects within EU geography. Data residency enforced via S3
|
|
714
|
+
bucket policies, BigQuery dataset location constraints, and Azure
|
|
715
|
+
geography restrictions.
|