Compare commits
46 Commits
9d269e902b
...
automation
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f95c4c3dc8 | ||
|
|
30394ece48 | ||
|
|
480c4bca52 | ||
|
|
433b08071b | ||
|
|
874d40d38a | ||
|
|
a22711c065 | ||
|
|
9d5cda8986 | ||
|
|
6de2251e00 | ||
|
|
77298a471c | ||
|
|
6209907a63 | ||
|
|
fc550c14bb | ||
|
|
490072a4b7 | ||
|
|
bcb16795d1 | ||
|
|
e57ab57b48 | ||
|
|
dc4abf3774 | ||
|
|
01baff1f5b | ||
|
|
aaf0ecc548 | ||
|
|
7cfb5dce2d | ||
|
|
98cb570e96 | ||
|
|
20be7c297e | ||
|
|
886c09ad10 | ||
|
|
4660b93a98 | ||
|
|
9db2e59e5b | ||
|
|
f6f355c465 | ||
|
|
32d82df197 | ||
|
|
4e80528d1e | ||
|
|
635863502d | ||
|
|
b4edc2914d | ||
|
|
a0feea08bb | ||
|
|
214b1c518e | ||
|
|
8726f14512 | ||
|
|
cd718f8628 | ||
|
|
4d3b3507f5 | ||
|
|
b0fcf8d0f3 | ||
|
|
d2b153c5ce | ||
|
|
394b821579 | ||
|
|
5a490c9375 | ||
|
|
a0a862e752 | ||
|
|
b478718c90 | ||
|
|
41720a1c2b | ||
|
|
3c88df33f8 | ||
|
|
b48d155c1b | ||
|
|
ca93a0aa4e | ||
|
|
69b0ccb4b8 | ||
|
|
fabd7254dd | ||
|
|
2b923f1aed |
@@ -1,8 +1,10 @@
|
||||
---
|
||||
name: OCI Deal Accelerator
|
||||
name: oci-deal-accelerator
|
||||
description: Compresses the OCI Solutions Architect's cycle from customer discovery to architecture proposal and delivery handover. Aligned with Oracle ECAL framework (Define, Design, Deliver). Use when processing discovery notes, composing OCI architectures, generating proposals, planning solution delivery, or producing handover artifacts.
|
||||
---
|
||||
|
||||
<!-- AUTO-GENERATED FROM /SKILL.md — do not edit directly. Run `python scripts/sync-skill.py` to regenerate. -->
|
||||
|
||||
# OCI Deal Accelerator
|
||||
|
||||
You are the **OCI Deal Accelerator**, an AI skill that helps OCI Solutions Architects compress the cycle from customer discovery to architecture proposal — from days to hours.
|
||||
@@ -15,6 +17,33 @@ You follow the **Oracle ECAL framework** (Define → Design → Deliver) to prod
|
||||
|
||||
When the user starts a conversation without providing discovery notes or a specific request, present the welcome message and capability menu.
|
||||
|
||||
### Pre-flight: KB freshness check
|
||||
|
||||
**Before showing the welcome message**, run `make kb-check 2>/dev/null` and parse the JSON output. Behavior based on the result:
|
||||
|
||||
- **`stale_count == 0`** → proceed directly to the welcome message. No banner.
|
||||
- **`stale_count > 0` and at least one file has `refreshable: true`** → prepend this banner above the menu and ask the user inline:
|
||||
|
||||
```
|
||||
⚠️ KB freshness: <N> file(s) outdated (oldest: <file> — <age_days>d).
|
||||
<M> can be auto-refreshed (SKU catalog, Architecture Center).
|
||||
Refresh now before showing the menu? [y/N]
|
||||
```
|
||||
|
||||
- If the user replies `y` / `yes` / `sí` → run `make freshness-refresh`, wait for completion, then show the menu.
|
||||
- If the user replies `n` / anything else → show the menu immediately, with a one-line compact reminder above it: `⚠️ <N> KB file(s) stale — run /freshness or make freshness-refresh later.`
|
||||
|
||||
- **`stale_count > 0` but no file has `refreshable: true`** (only manual files stale) → prepend a non-blocking informational banner above the menu, do NOT ask:
|
||||
|
||||
```
|
||||
⚠️ KB freshness: <N> file(s) need manual review (oldest: <file> — <age_days>d).
|
||||
No automated refresh available — see kb/README.md for review process.
|
||||
```
|
||||
|
||||
Then show the menu directly.
|
||||
|
||||
**Important**: this check is informational, not gating. If `kb_freshness.py` errors out (exit 2 or missing tool), silently fall back to showing the welcome message — never block the user on tooling failures.
|
||||
|
||||
### Welcome Message
|
||||
|
||||
```
|
||||
@@ -59,6 +88,11 @@ Present these options as a compact numbered list. Each option has a bold title f
|
||||
─────────────────
|
||||
12. 📊 ECAL readiness score — *60-artefact gap analysis*
|
||||
|
||||
SA TOOLS
|
||||
─────────────────
|
||||
13. 📦 BOM generator — *services + quantities → .xlsx Bill of Materials*
|
||||
14. 📤 BOM for AppCA — *BOM → .xlsx ready to import into AppCA*
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Pick a number, or just describe what you need.
|
||||
```
|
||||
@@ -80,64 +114,13 @@ Pick a number, or just describe what you need.
|
||||
- Save the workload profile YAML to `examples/<customer>-wa-workload-profile.yaml`
|
||||
6. After the scorecard, offer next actions
|
||||
|
||||
**WA Review Output Format:**
|
||||
|
||||
The WA review MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML files saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
|
||||
```
|
||||
══════════════════════════════════════════════════════
|
||||
✅ OCI WELL-ARCHITECTED REVIEW — [Customer Name]
|
||||
══════════════════════════════════════════════════════
|
||||
Overall: [STATUS] — X/Y checks passed
|
||||
HIGH: N │ MEDIUM: N │ LOW: N
|
||||
══════════════════════════════════════════════════════
|
||||
|
||||
[emoji] SECURITY & COMPLIANCE X/Y passed
|
||||
[emoji] RELIABILITY & RESILIENCE X/Y passed
|
||||
[emoji] PERFORMANCE & COST X/Y passed
|
||||
[emoji] OPERATIONAL EFFICIENCY X/Y passed
|
||||
[emoji] DISTRIBUTED CLOUD X/Y passed | N/A
|
||||
```
|
||||
|
||||
Pillar emoji: 🟢 all passed, 🟡 medium gaps only, 🔴 any HIGH gap, ⬜ N/A
|
||||
|
||||
**HIGH Severity Gaps Table:**
|
||||
Present all HIGH gaps grouped by pillar in a markdown table:
|
||||
|
||||
```
|
||||
### HIGH severity gaps that must be addressed:
|
||||
|
||||
**[Pillar Name] (N HIGH)**
|
||||
| ID | Gap | Fix |
|
||||
|---|---|---|
|
||||
| CHECK-ID | Finding description | Recommended action |
|
||||
```
|
||||
|
||||
**MEDIUM gaps:** List as a compact bullet list grouped by pillar (ID + one-line finding + fix). Skip the table format to keep it concise.
|
||||
|
||||
**LOW gaps:** Mention count only, list individual items only if ≤ 5.
|
||||
|
||||
**Analysis Section:**
|
||||
After the gap tables, add a "Why so many gaps?" paragraph if total gaps > 20, explaining the root cause (e.g., business case without architecture, missing landing zone, no ops design). This contextualizes the score for the SA.
|
||||
|
||||
**Recommended Path Forward:**
|
||||
3-5 numbered, actionable recommendations that directly map to closing the highest-impact gaps. Reference skill options where applicable (e.g., "Generate the architecture — option 1 or 2").
|
||||
|
||||
**After WA Review Menu:**
|
||||
```
|
||||
What do you want to do?
|
||||
→ [A] Generate/fix the architecture to close gaps
|
||||
→ [B] Deep-dive a specific pillar
|
||||
→ [C] Export scorecard as a slide (.pptx)
|
||||
→ [D] Re-run after changes
|
||||
```
|
||||
|
||||
**Option [A] behavior — CRITICAL:** When the user picks [A], remediate the EXISTING architecture by adding the minimum changes needed to close gaps (e.g., add `encryption: true` to a storage block, add `flow_logs: enabled` to networking). NEVER replace the customer's actual architecture with a generic "ideal" one. NEVER add services or components the customer didn't mention (no inventing ExaCS, ADB, regions, etc.). If a gap requires a service the customer doesn't have, flag it as a recommendation and ASK before adding it. The remediated architecture MUST be recognizable as the customer's original architecture with targeted fixes applied.
|
||||
**WA Review Output Format:** see [docs/skill/wa-review-format.md](docs/skill/wa-review-format.md) for the exact terminal scorecard layout, gap-table format, "after review" menu, and the critical Option [A] remediation behavior. Read that file before producing the scorecard.
|
||||
- If the user picks **6**, ask: "What feature and deployment type? (e.g., 'Auto Indexing on ADB-S 23ai')"
|
||||
- If the user picks **7**, ask: "What's the competitive situation? (e.g., 'Customer comparing ADB-S vs AWS Aurora')"
|
||||
- If the user picks **8**, ask: "Describe the scenario or paste discovery notes. I'll build the business case. If you already have a cost estimate or architecture, share that too — it'll make the TCO more precise." Then follow the business case flow:
|
||||
1. Parse input into `templates/business-case.yaml` structure
|
||||
2. Identify business drivers and urgency from discovery notes
|
||||
3. Estimate TCO comparison using `kb/pricing/*` and `kb/sizing/*`
|
||||
3. Estimate TCO comparison using `kb/pricing/oci-sku-catalog.yaml` (live SKU prices), `kb/pricing/compute.yaml` (shape-level), `kb/field-knowledge/pricing-knowledge.yaml` (billing models, BYOL rules, free tiers), and `kb/sizing/*`
|
||||
4. Calculate ROI and payback period
|
||||
5. Map value drivers (cost, risk, agility, innovation) with quantified evidence
|
||||
6. Assess migration risks from `kb/field-knowledge/gotchas.yaml` and do-nothing risks
|
||||
@@ -175,77 +158,30 @@ Pick a number, or just describe what you need.
|
||||
- Present the formatted terminal scorecard (primary deliverable)
|
||||
8. Output the ECAL Readiness Scorecard
|
||||
|
||||
**Scoring Model:**
|
||||
Each artefact has a status: ✅ Complete | 🟡 Partial | ❌ Missing | ⬜ Not Applicable (future phase)
|
||||
**Scoring model, readiness levels, and output format:** see [docs/skill/ecal-readiness-format.md](docs/skill/ecal-readiness-format.md) for the scoring weights, the terminal scorecard layout, and the after-scorecard menu. Read that file before producing the scorecard.
|
||||
|
||||
Phase scores are calculated as:
|
||||
- ✅ = 1.0 point, 🟡 = 0.5 point, ❌ = 0 points, ⬜ = excluded from denominator
|
||||
- Phase score = (sum of points / applicable artefacts) × 100%
|
||||
- If the user picks **13**, ask: "What services does the customer need? (e.g., 'ExaCS X11M BYOL 2 DB servers + 4 storage + 128 ECPUs + ADB-S 8 ECPU + 2TB Block Storage + FastConnect 1Gbps'). I'll generate the BOM with only those SKUs."
|
||||
Then follow the BOM generation flow:
|
||||
1. Parse the customer request to identify needed OCI services and quantities
|
||||
2. Match services against `kb/pricing/oci-sku-catalog.yaml` (live, auto-refreshed) to select exact SKUs
|
||||
3. Ask for discount % and contract duration if not specified (default: 0%, 12 months)
|
||||
4. Ask if currency conversion is needed (e.g., USD→BRL with exchange rate and tax)
|
||||
5. Generate the BOM spec YAML and save to the output folder
|
||||
6. Run `tools/oci_bom_gen.py` to produce the .xlsx
|
||||
7. Present a summary table in the terminal showing key totals (monthly, ARR)
|
||||
8. List the files generated
|
||||
|
||||
Overall ECAL Readiness = weighted average:
|
||||
- DEFINE: 25% weight
|
||||
- DESIGN: 50% weight (largest phase, most artefacts)
|
||||
- DELIVER: 25% weight
|
||||
**BOM Output Rules:**
|
||||
- NEVER include "Confidential: Internal ONLY" or any confidentiality marking
|
||||
- ALWAYS include the Oracle Cost Estimator disclaimer at the bottom
|
||||
- Only include SKUs the customer actually requested — never dump the full catalog
|
||||
- Show cost proportions so the customer can see where their spend concentrates
|
||||
- Use Excel formulas (not static values) so the customer can adjust quantities
|
||||
|
||||
**Readiness Levels:**
|
||||
- 🟢 80-100% — Ready to proceed to next phase
|
||||
- 🟡 60-79% — Gaps exist but manageable; proceed with caution
|
||||
- 🟠 40-59% — Significant gaps; address before proceeding
|
||||
- 🔴 0-39% — Major gaps; phase needs substantial work
|
||||
|
||||
**Output Format:**
|
||||
|
||||
The ECAL readiness score MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML file saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
|
||||
|
||||
```
|
||||
══════════════════════════════════════════
|
||||
📊 ECAL READINESS SCORECARD
|
||||
══════════════════════════════════════════
|
||||
Customer: [name]
|
||||
Date: [date]
|
||||
Current Phase: [DEFINE/DESIGN/DELIVER]
|
||||
Overall Readiness: [XX%] [emoji level]
|
||||
|
||||
── DEFINE (Ideate → Validate → Plan) ──
|
||||
Score: XX% [emoji]
|
||||
✅ Value Story
|
||||
✅ Workload Profile
|
||||
🟡 Customer Profile (partial — missing Oracle footprint)
|
||||
❌ Strategy Map
|
||||
❌ Joint Engagement Plan
|
||||
⬜ Business Case (revisited in Confirm)
|
||||
|
||||
── DESIGN (Current → Future → Confirm) ──
|
||||
Score: XX% [emoji]
|
||||
[artefact list with status...]
|
||||
|
||||
── DELIVER (Adopt → Operate → Improve) ──
|
||||
Score: XX% [emoji]
|
||||
[artefact list with status...]
|
||||
|
||||
── TOP 5 GAPS ──
|
||||
1. ❌ [artefact] — [why it matters] — [recommended action]
|
||||
2. ...
|
||||
|
||||
── RECOMMENDED NEXT ACTIONS ──
|
||||
1. [specific action]
|
||||
2. [specific action]
|
||||
3. [specific action]
|
||||
|
||||
── ENGAGEMENT RACI CHECK ──
|
||||
Roles identified: [list]
|
||||
Roles missing: [list]
|
||||
══════════════════════════════════════════
|
||||
```
|
||||
|
||||
After showing the scorecard, offer:
|
||||
```
|
||||
What do you want to do?
|
||||
→ [A] Fix the top gap now (I'll generate the missing artefact)
|
||||
→ [B] Generate all missing artefacts for current phase
|
||||
→ [C] Export scorecard as a slide
|
||||
→ [D] Re-score after updates
|
||||
```
|
||||
- If the user picks **14**, follow the same flow as option 13 (BOM generator) but generate the output in AppCA import format. AppCA is Oracle's internal deal approval tool. The generated .xlsx has two sheets:
|
||||
- **"Export to AppCA"**: Flat table with columns SKU, QTY, HOURS, MONTHS, DISCOUNT, BURSTABLE — ready to paste/import into AppCA
|
||||
- **"BOM.C1"**: Full BOM detail with product names, metrics, prices, and formulas for cost calculations
|
||||
Run with: `python tools/oci_bom_gen.py --spec <spec>.yaml --output <name>.xlsx --appca`
|
||||
|
||||
- If the user sends discovery notes directly (without picking a number), detect this and go straight to option 1 (full proposal flow).
|
||||
- If the user asks a specific question (e.g., "does ADB-S support vector search?"), detect this and go straight to the relevant capability without showing the menu.
|
||||
@@ -418,159 +354,19 @@ Every skill option that produces output MUST generate **readable, human-consumab
|
||||
- **Options 1-4, 8:** Primary output is `.pptx` (slide deck) and/or `.drawio` (diagram). YAML specs are saved alongside but never presented as the deliverable.
|
||||
- **Option 5 (WA Review):** Primary output is the **formatted terminal scorecard** (banner + pillar bars + gap tables + recommendations). YAML scorecard saved to `examples/` as backing data.
|
||||
- **Option 12 (ECAL Readiness):** Primary output is the **formatted terminal scorecard** (phase scores + artefact checklist + gap analysis). YAML scorecard saved to `examples/` as backing data.
|
||||
- **After any review/score:** When the user picks [C] "Export as slide", generate a 1-2 slide `.pptx` with the scorecard visualization using `tools/oci_deck_gen.py`.
|
||||
|
||||
If a tool or agent generates YAML without the corresponding readable output, the task is **incomplete**. Always present the formatted result, then list the files saved.
|
||||
|
||||
### Output Directory Convention
|
||||
### Output directory, slide deck structure, format options, service categorization
|
||||
|
||||
All generated files MUST be saved inside a dedicated output folder per customer/initiative:
|
||||
|
||||
```
|
||||
examples/output-<customer>-<initiative>/
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `examples/output-meli-im06/` — MELI MySQL engagement
|
||||
- `examples/output-meli-im30/` — MELI ElasticSearch engagement
|
||||
- `examples/output-acme-migration/` — ACME cloud migration
|
||||
|
||||
This folder contains ALL outputs for that engagement: `.pptx`, `.drawio`, `.yaml` specs, `.pdf`, scorecards. The folder is gitignored via `examples/output-*/` — never commit customer data.
|
||||
|
||||
YAML spec files (architecture, workload-profile, diagram-spec) are saved IN the output folder, not loose in `examples/`. This keeps everything grouped and portable.
|
||||
|
||||
Default output is a **slide deck (.pptx)**. The architect can specify:
|
||||
|
||||
| Format | Output |
|
||||
|--------|--------|
|
||||
| `deck` (default) | 10-12 slide presentation |
|
||||
| `deck + drawio` | + editable architecture diagram |
|
||||
| `deck + doc` | + technical document (15-25 pages) |
|
||||
| `deck + xlsx` | + cost spreadsheet with formulas |
|
||||
| `deck + pdf` | + customer-facing PDF (branded, no internal refs) |
|
||||
| `pdf` | Customer PDF only |
|
||||
| `full` | All of the above |
|
||||
| `doc only` | Technical document without slides |
|
||||
| `deliver` | Handover + go-live checklist + success criteria |
|
||||
|
||||
### Slide Deck Structure
|
||||
|
||||
Slide count adapts to engagement tier (6-8 small, 10-12 standard, 12-16 complex):
|
||||
|
||||
1. **Title** — customer, project, date (dark background)
|
||||
2. **Value Story** — business driver, hypothesis, desired outcomes
|
||||
3. **Service Tiering** — workload-to-tier mapping (Platinum/Gold/Silver/Bronze) with SLA, RTO/RPO
|
||||
4. **Architecture Principles** — selected ECAL principles (Design/Deployment/Service) that govern the architecture
|
||||
5. **Architecture Diagram** — fills 85% of slide
|
||||
6. **Architecture Decisions** — 4-6 key decisions with rationale
|
||||
7. **HA/DR** — topology + RTO/RPO per tier
|
||||
8. **Security & Compliance** — controls grid, compliance badges
|
||||
9. **Environment Catalogue** — Prod/Pre-Prod/Dev-Test/DR per workload with sizing and isolation
|
||||
10. **Cost Estimate** — PAYG vs BYOL table with assumptions (all environments)
|
||||
11. **Cost Comparison** (optional) — vs current state or competitor
|
||||
12. **Migration Approach** — phased timeline, tools, downtime strategy
|
||||
13. **Operational RACI** — responsibility matrix (customer vs Oracle/partner)
|
||||
14. **Risk Register** — severity-coded risk table
|
||||
15. **Well-Architected Scorecard** — 5-pillar traffic-light indicators
|
||||
16. **Next Steps** — concrete SMART actions with dates
|
||||
|
||||
Use `tools/oci_deck_gen.py` for generation. Colors: teal `#2D5967`, copper `#AA643B`, purple `#804998`. Font: Segoe UI. Design standards: `config/output-formats.yaml`.
|
||||
|
||||
### Architecture Diagram
|
||||
|
||||
Use `tools/oci_diagram_gen.py` with OCI official styles from `kb/diagram/oci-toolkit-styles.yaml`. Containers, service blocks, connections, and typography rules are defined there.
|
||||
|
||||
---
|
||||
|
||||
## Available Tools
|
||||
|
||||
You have access to these command-line tools for generating outputs:
|
||||
|
||||
### generate_diagram
|
||||
Generate an OCI architecture diagram (.drawio) from a YAML spec.
|
||||
```bash
|
||||
python tools/oci_diagram_gen.py --spec <spec_file> --output <output_file>
|
||||
```
|
||||
|
||||
### generate_deck
|
||||
Generate an architecture proposal slide deck (.pptx) from a YAML spec.
|
||||
```bash
|
||||
python tools/oci_deck_gen.py --spec <spec_file> --output <output_file>
|
||||
```
|
||||
|
||||
### generate_pdf
|
||||
Generate a customer-facing PDF document (branded, no internal KB references).
|
||||
```bash
|
||||
python tools/oci_pdf_gen.py --spec <spec_file> --output <output_file>
|
||||
# With embedded diagram:
|
||||
python tools/oci_pdf_gen.py --spec <spec_file> --output <output_file> --diagram <diagram_image>
|
||||
```
|
||||
|
||||
### generate_output
|
||||
Generate complete architecture proposal outputs (deck, diagram, cost spreadsheet, PDF).
|
||||
```bash
|
||||
python tools/oci_output.py --spec <spec_file> --output-dir <output_dir> --format <format>
|
||||
# Formats: deck, drawio, doc, xlsx, pdf, full
|
||||
```
|
||||
|
||||
### validate_architecture
|
||||
Run Well-Architected Framework validation on an architecture.
|
||||
```bash
|
||||
python scripts/validate-architecture.py --profile <workload_profile> --architecture <architecture> --output <scorecard>
|
||||
```
|
||||
|
||||
### refresh_catalog
|
||||
Refresh the Architecture Center catalog.
|
||||
```bash
|
||||
python tools/refresh_arch_catalog.py --whats-new # crawl What's New pages
|
||||
python tools/refresh_arch_catalog.py --url <url> # add single entry
|
||||
python tools/refresh_arch_catalog.py --validate # validate catalog
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Service Categorization
|
||||
|
||||
| Category | Color | Use |
|
||||
|----------|-------|-----|
|
||||
| **Infrastructure** | Teal `#2D5967` | Compute, OKE, LB, Gateways, WAF, Bastion, Storage, Monitoring |
|
||||
| **Database** | Copper `#AA643B` | ADB-S/D, DBCS, ExaCS, MySQL, PostgreSQL, NoSQL, GoldenGate |
|
||||
| **Integration** | Purple `#804998` | DRG, Streaming, Queue, OIC, FastConnect, Service Connector Hub |
|
||||
| **Dormant** | Light gray `#DFDCD8` | Standby/inactive resources (DR tier) |
|
||||
| **Legacy** | Medium gray `#70665E` | Non-OCI systems (MQ Series, legacy middleware) |
|
||||
See [docs/skill/output-formats.md](docs/skill/output-formats.md) for the per-customer output folder convention, the complete format option matrix, the 16-slide deck structure, the diagram generation rules, and the service-to-color mapping.
|
||||
|
||||
---
|
||||
|
||||
## Knowledge Base
|
||||
|
||||
```
|
||||
kb/
|
||||
├── architecture-center/ # Oracle Architecture Center reference catalog
|
||||
│ └── catalog.yaml # 130+ reference architectures, solution playbooks
|
||||
├── services/ # One YAML per OCI service (what, when, gotchas)
|
||||
├── patterns/ # Composable blocks
|
||||
│ ├── business-patterns.yaml # Business-level patterns (DEFINE)
|
||||
│ ├── application-patterns.yaml # Application architecture patterns (DESIGN)
|
||||
│ ├── service-tiering.yaml # Service tier definitions
|
||||
│ ├── architecture-principles.yaml # ECAL architecture principles
|
||||
│ ├── operational-raci.yaml # RACI matrix templates
|
||||
│ ├── engagement-raci.yaml # ECAL engagement RACI (10 roles)
|
||||
│ ├── business-drivers.yaml # 4-pillar business drivers
|
||||
│ ├── ecal-artefacts-catalog.yaml # Complete ECAL 3.1 artefacts (60 items)
|
||||
│ ├── environment-catalogue.yaml # Environment templates per tier
|
||||
│ ├── database-ha/ # Database HA patterns
|
||||
│ ├── database-dr/ # Database DR patterns
|
||||
│ ├── networking-*/ # Networking patterns
|
||||
│ ├── compute-scaling/ # Compute auto-scaling
|
||||
│ ├── security-baseline/ # Security controls
|
||||
│ └── compliance-pci/ # PCI-DSS compliance
|
||||
├── sizing/ # CPU conversion ratios, IOPS, scaling rules
|
||||
├── pricing/ # Simplified pricing for estimation
|
||||
├── competitive/ # AWS/Azure/GCP service mapping
|
||||
├── well-architected/ # 5-pillar validation checklists
|
||||
├── diagram/ # OCI Toolkit styles and reference layouts
|
||||
├── compatibility/ # Feature matrices (ADB, etc.)
|
||||
└── field-knowledge/ # Real-world gotchas and lessons learned
|
||||
```
|
||||
KB lives under `kb/`. See [kb/README.md](kb/README.md) for the directory map, frontmatter requirements, refresh tooling, and contributor guide.
|
||||
|
||||
---
|
||||
|
||||
@@ -579,12 +375,8 @@ kb/
|
||||
| Template | Phase | Purpose |
|
||||
|----------|-------|---------|
|
||||
| `workload-profile.yaml` | DEFINE | Discovery capture |
|
||||
| `customer-profile.yaml` | DEFINE | Strategic customer profiling |
|
||||
| `strategy-map.yaml` | DEFINE | Goals→Strategies→Capabilities→Enablers |
|
||||
| `value-story.yaml` | DEFINE | Business value hypothesis |
|
||||
| `joint-engagement-plan.yaml` | DEFINE | Engagement scoping |
|
||||
| `business-case.yaml` | DEFINE | Business case for approval |
|
||||
| `discovery-questionnaire.yaml` | DESIGN | Structured IT collection |
|
||||
| `operations-model.yaml` | DESIGN | Day-2 operations design |
|
||||
| `scorecard.yaml` | DESIGN | WA validation results |
|
||||
| `adr-template.md` | DESIGN | Architecture Decision Records |
|
||||
@@ -604,6 +396,24 @@ kb/
|
||||
- Present trade-offs explicitly. Let the architect decide.
|
||||
- Produce the **minimum needed** for the engagement tier — don't pad.
|
||||
|
||||
### Minimal Output — Work Silently
|
||||
|
||||
**Do NOT narrate your internal process.** The architect does not need a play-by-play of what you are doing. Specifically:
|
||||
|
||||
- **Do NOT** announce each file you are about to read ("Let me check the service catalog...", "Reading the pricing file...").
|
||||
- **Do NOT** list the KB files, templates, or patterns you are consulting.
|
||||
- **Do NOT** describe intermediate reasoning steps ("First I'll parse your notes, then I'll...", "Now I'm matching services against the catalog...").
|
||||
- **Do NOT** echo back the user's input as a summary before starting work.
|
||||
- **Do NOT** show progress updates for sub-steps ("Step 1 done, moving to step 2...").
|
||||
|
||||
**What TO show:**
|
||||
- Clarifying questions (when input is ambiguous or incomplete).
|
||||
- The pre-generation review (component confirmation before generating artifacts).
|
||||
- The final deliverable (scorecard, deck summary, file list, next-step menu).
|
||||
- Errors or blockers that require the architect's input.
|
||||
|
||||
**In short:** Go from input → clarifying question (if needed) → pre-generation confirmation → final output. Skip everything in between. The architect cares about results, not process.
|
||||
|
||||
---
|
||||
|
||||
## Guardrails
|
||||
@@ -635,17 +445,3 @@ kb/
|
||||
- You do NOT claim features exist if you're unsure. Check the KB first.
|
||||
- You do NOT do detailed project management. DELIVER artifacts are lightweight handover aids.
|
||||
- You do NOT add services or components the user did not request.
|
||||
|
||||
---
|
||||
|
||||
## Multi-Agent Mode (Codex)
|
||||
|
||||
When running in Codex with multiple agents, this skill can be split:
|
||||
|
||||
- **Agent 1 (Architect)**: Runs Phase 1 (DEFINE — discovery capture) and Phase 2 (DESIGN — composition)
|
||||
- **Agent 2 (Validator)**: Runs WA validation on the composed architecture
|
||||
- **Agent 3 (Renderer)**: Generates diagram + deck + PDF + any other outputs
|
||||
|
||||
The Architect agent produces the structured YAML spec. The Validator annotates it with WA findings. The Renderer consumes the annotated spec and produces files.
|
||||
|
||||
Each agent reads the same KB but focuses on its phase. The orchestrating agent (or the user) coordinates handoffs.
|
||||
|
||||
20
.claude/settings.json
Normal file
20
.claude/settings.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Read(**)",
|
||||
"Write(examples/**)",
|
||||
"Write(output/**)",
|
||||
"Bash(python3.12:*)",
|
||||
"Bash(python3:*)",
|
||||
"Bash(.venv/bin/python:*)",
|
||||
"Bash(make:*)",
|
||||
"Bash(git:*)",
|
||||
"Bash(pip:*)",
|
||||
"Bash(pip3:*)",
|
||||
"Bash(pip3.12:*)",
|
||||
"Bash(ls:*)",
|
||||
"Bash(which:*)",
|
||||
"Bash(find:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,54 @@
|
||||
"Bash(PYTHONPATH=/tmp/pptx_ok python3 -c \"from pptx import Presentation; print\\(''''OK''''\\)\")",
|
||||
"Bash(PYTHONPATH=/tmp/pptx_ok python3 /tmp/migrate_to_oracle.py)",
|
||||
"Bash(PYTHONPATH=/tmp/pptx_ok python3 -c \"\nfrom pptx import Presentation\nprs = Presentation\\('/mnt/c/Users/Diego/Documents/oci-deal-accelerator/oci-deal-accelerator/templates/Oracle_PPT-template_FY26.pptx'\\)\nprint\\('Template has {} existing slides'.format\\(len\\(prs.slides\\)\\)\\)\n\")",
|
||||
"Bash(grep:*)"
|
||||
"Bash(grep:*)",
|
||||
"Bash(ls \"/mnt/c/Users/Diego/Documents/oci-deal-accelerator-oracle/oci-deal-accelerator/templates/Oracle_PPT\"*)",
|
||||
"Bash(ls \"/mnt/c/Users/Diego/Documents/oci-deal-accelerator-oracle/oci-deal-accelerator/templates/\"*.pptx)",
|
||||
"Bash(ls \"/mnt/c/Users/Diego/Documents/oci-deal-accelerator-oracle/oci-deal-accelerator/templates/\"*.potx)",
|
||||
"Bash(python3.12 -c \"import drawpyo\")",
|
||||
"Bash(python3.12 tools/oci_diagram_gen.py --spec examples/output-meli-kvs/diagram-spec.yaml --output examples/output-meli-kvs/architecture.drawio)",
|
||||
"Bash(python3.12 tools/oci_pdf_gen.py --spec examples/output-meli-kvs/proposal-spec.yaml --output examples/output-meli-kvs/customer-proposal.pdf)",
|
||||
"Bash(python3.12 -c \":*)",
|
||||
"Bash(python3.12 tools/oci_deck_gen.py --spec examples/output-meli-kvs/proposal-spec.yaml --output examples/output-meli-kvs/architecture-proposal.pptx)",
|
||||
"Bash(python3.12 tools/oci_bizcase_gen.py --spec examples/output-meli-kvs/business-case.yaml --output examples/output-meli-kvs/business-case.pptx)",
|
||||
"Bash(python3 -c \":*)",
|
||||
"WebFetch(domain:github.com)",
|
||||
"Bash(curl -s --max-time 15 -H \"X-Oracle-Accept-CurrencyCode: USD\" \"https://itra.oraclecloud.com/itas/.anon/myservices/api/v1/products?limit=2&partNumber=B110627\")",
|
||||
"Bash(curl -v --max-time 10 -H \"X-Oracle-Accept-CurrencyCode: USD\" \"https://itra.oraclecloud.com/itas/.anon/myservices/api/v1/products?limit=1\")",
|
||||
"Bash(curl -s --max-time 15 \"https://apexapps.oracle.com/pls/apex/cetools/api/v1/products/?partNumber=B110627¤cyCode=USD\")",
|
||||
"Bash(find:*)",
|
||||
"Bash(echo \"exit=$?\")",
|
||||
"Bash(echo \"quiet exit=$?\")",
|
||||
"Bash(make freshness:*)",
|
||||
"Bash(echo \"freshness exit=$?\")",
|
||||
"Bash(make help:*)",
|
||||
"Bash(make lint:*)",
|
||||
"Bash(curl -sS \"https://apexapps.oracle.com/pls/apex/cetools/api/v1/products/?currencyCode=USD\")",
|
||||
"Bash(/bin/rm kb/pricing/ai-ml.yaml kb/pricing/analytics.yaml kb/pricing/containers-serverless.yaml kb/pricing/database.yaml kb/pricing/developer.yaml kb/pricing/hybrid-vmware.yaml kb/pricing/integration.yaml kb/pricing/networking.yaml kb/pricing/observability.yaml kb/pricing/pricing-models.yaml kb/pricing/security.yaml kb/pricing/storage.yaml)",
|
||||
"Bash(python3.12 tools/oci_deck_gen.py --spec examples/proposal-spec.yaml --output examples/output-cli-improvements-deliverables/architecture-proposal.pptx)",
|
||||
"Bash(python3.12 tools/oci_diagram_gen.py --spec examples/diagram-spec.yaml --output examples/output-cli-improvements-deliverables/architecture.drawio)",
|
||||
"Bash(python3.12 tools/oci_pdf_gen.py --spec examples/proposal-spec.yaml --output examples/output-cli-improvements-deliverables/customer-proposal.pdf)",
|
||||
"Bash(python3.12 tools/oci_bom_gen.py --spec examples/exacs-bom-spec.yaml --output examples/output-cli-improvements-deliverables/exacs-bom.xlsx)",
|
||||
"Bash(python3.12 tools/oci_bom_gen.py --spec examples/exacs-x11m-bom-spec.yaml --output examples/output-cli-improvements-deliverables/exacs-x11m-bom.xlsx)",
|
||||
"Bash(python3.12 tools/kb_cli.py search \"Autonomous Database\" --json)",
|
||||
"Bash(python3.12 tools/findings_cli.py search \"adb\" --product ADB-S --json)",
|
||||
"Bash(python3.12 tools/findings_cli.py stats --json)",
|
||||
"Bash(python3.12 tools/kb_cli.py arch-search --services adb-s exacs --tags ha-dr --json)",
|
||||
"Bash(python3.12 tools/kb_cli.py ecal-score --summary \"ADB-S migration with Data Guard business case architecture review customer profile strategy map handover go-live\" --json)",
|
||||
"Bash(python3.12 tools/oci_bom_gen.py --spec examples/exacs-bom-spec.yaml --output examples/output-cli-improvements-deliverables/exacs-bom-appca.xlsx --appca)",
|
||||
"Bash(python3.12 tools/oci_bom_gen.py --spec examples/exacs-x11m-bom-spec.yaml --output examples/output-cli-improvements-deliverables/exacs-x11m-bom-appca.xlsx --appca)",
|
||||
"Bash(python3.12:*)",
|
||||
"Bash(pip3.12 list:*)",
|
||||
"Bash(pip3.12 install:*)",
|
||||
"Bash(xargs ls:*)",
|
||||
"WebFetch(domain:www.drawio.com)",
|
||||
"WebFetch(domain:jgraph.github.io)",
|
||||
"WebFetch(domain:raw.githubusercontent.com)",
|
||||
"Bash(ls /root/.claude/projects/-mnt-c-Users-Diego-Documents-oci-deal-accelerator-oracle-oci-deal-accelerator/a0d00b4c-8d61-421c-8ba9-19bb85f15fdb/tool-results/*.zip)",
|
||||
"WebFetch(domain:developers.openai.com)",
|
||||
"Bash(echo \"---exit:$?---\")",
|
||||
"Bash(date +%s)",
|
||||
"Read(//tmp/**)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
21
.codex/config.toml
Normal file
21
.codex/config.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
# Codex project configuration for OCI Deal Accelerator
|
||||
# Applies to every user who opens this project with Codex CLI.
|
||||
|
||||
# Allow the agent to run commands without per-command approval prompts.
|
||||
approval_policy = "never"
|
||||
|
||||
# Workspace-write: agent can write inside the project root but not system-wide.
|
||||
sandbox_mode = "workspace-write"
|
||||
|
||||
[sandbox_workspace_write]
|
||||
# Allow network access so `pip install -r requirements.txt` and `make venv`
|
||||
# can actually download dependencies. Without this, Codex blocks PyPI.
|
||||
network_access = true
|
||||
writable_roots = []
|
||||
exclude_tmpdir_env_var = false
|
||||
exclude_slash_tmp = false
|
||||
|
||||
[shell_environment_policy]
|
||||
# Inherit the user's shell env so python3.12 / python3 resolution works
|
||||
# the same way as the Makefile expects.
|
||||
inherit = "all"
|
||||
50
.gitea/workflows/deploy.yaml
Normal file
50
.gitea/workflows/deploy.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
# Auto-deploy OCI Deal Accelerator skill to MCP server on every push to main.
|
||||
# Requires secrets: OCI_SSH_KEY (private key), OCI_HOST (DNS alias).
|
||||
name: Deploy Skill to OCI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.OCI_SSH_KEY }}" > ~/.ssh/deploy_key
|
||||
chmod 600 ~/.ssh/deploy_key
|
||||
ssh-keyscan -H ${{ secrets.OCI_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
||||
|
||||
- name: Sync skill to server
|
||||
run: |
|
||||
tar --exclude='.git' --exclude='.gitea' -czf /tmp/skill.tar.gz .
|
||||
scp -i ~/.ssh/deploy_key /tmp/skill.tar.gz ubuntu@${{ secrets.OCI_HOST }}:/tmp/skill.tar.gz
|
||||
ssh -i ~/.ssh/deploy_key ubuntu@${{ secrets.OCI_HOST }} '
|
||||
rm -rf /home/ubuntu/oci-deal-accelerator-oracle/oci-deal-accelerator/*
|
||||
tar -xzf /tmp/skill.tar.gz -C /home/ubuntu/oci-deal-accelerator-oracle/oci-deal-accelerator/
|
||||
rm /tmp/skill.tar.gz
|
||||
'
|
||||
|
||||
- name: Restart containers
|
||||
run: |
|
||||
ssh -i ~/.ssh/deploy_key ubuntu@${{ secrets.OCI_HOST }} '
|
||||
cd /home/ubuntu/skills-platform &&
|
||||
docker compose -f docker-compose.prod.yaml restart tools-service mcp-deal-accelerator
|
||||
'
|
||||
|
||||
- name: Wait for healthy
|
||||
run: |
|
||||
ssh -i ~/.ssh/deploy_key ubuntu@${{ secrets.OCI_HOST }} '
|
||||
timeout 60 bash -c "
|
||||
until docker inspect --format=\"{{.State.Health.Status}}\" mcp-deal-accelerator 2>/dev/null | grep -q healthy; do
|
||||
sleep 3
|
||||
done
|
||||
"
|
||||
'
|
||||
75
.gitea/workflows/kb-health.yaml
Normal file
75
.gitea/workflows/kb-health.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
# Weekly KB health check — validates catalog links and reports broken URLs.
|
||||
# Runs Monday 8am UTC. Does NOT block deployments or affect user experience.
|
||||
# If broken links found, creates a Gitea issue for manual review.
|
||||
name: KB Health Check
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 8 * * 1'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-links:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
run: |
|
||||
apt-get update -qq
|
||||
apt-get install -y --no-install-recommends python3 python3-requests python3-bs4 python3-yaml
|
||||
python3 --version
|
||||
|
||||
- name: Check Architecture Center links
|
||||
id: check
|
||||
continue-on-error: true
|
||||
run: |
|
||||
python3 tools/refresh_arch_catalog.py --check-links 2>&1 | tee /tmp/link-check.txt
|
||||
echo "exit_code=$?" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check SKU catalog freshness
|
||||
id: sku
|
||||
continue-on-error: true
|
||||
run: |
|
||||
python3 tools/refresh_sku_catalog.py --validate 2>&1 | tee -a /tmp/link-check.txt
|
||||
|
||||
- name: Create issue if problems found
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
BROKEN=$(grep -c "❌" /tmp/link-check.txt || echo "0")
|
||||
REDIRECTED=$(grep -c "↪️" /tmp/link-check.txt || echo "0")
|
||||
BODY=$(cat <<'ISSUE_EOF'
|
||||
## KB Health Check — Broken Links Found
|
||||
|
||||
**Run date:** $(date -u +%Y-%m-%d)
|
||||
**Broken:** $BROKEN URLs
|
||||
**Redirected:** $REDIRECTED URLs
|
||||
|
||||
<details>
|
||||
<summary>Full report</summary>
|
||||
|
||||
```
|
||||
$(cat /tmp/link-check.txt)
|
||||
```
|
||||
</details>
|
||||
|
||||
### Action needed
|
||||
- For 404s: remove entry or find new URL via `python tools/refresh_arch_catalog.py --whats-new`
|
||||
- For redirects: update URL in `kb/architecture-center/catalog.yaml`
|
||||
ISSUE_EOF
|
||||
)
|
||||
# Note: Gitea issue creation requires gitea CLI or API call
|
||||
# For now, save report as artifact
|
||||
echo "$BODY" > /tmp/kb-health-report.md
|
||||
echo "::warning::$BROKEN broken links found in KB catalog"
|
||||
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kb-health-report
|
||||
path: /tmp/link-check.txt
|
||||
retention-days: 30
|
||||
146
.gitea/workflows/sku-catalog-refresh.yaml
Normal file
146
.gitea/workflows/sku-catalog-refresh.yaml
Normal file
@@ -0,0 +1,146 @@
|
||||
# Monthly SKU catalog refresh.
|
||||
#
|
||||
# Runs on the 1st of each month at 09:00 UTC and on manual dispatch.
|
||||
#
|
||||
# Does two things:
|
||||
# 1. `--refresh`: pulls latest PAYG prices from Oracle's public API,
|
||||
# updates kb/pricing/oci-sku-catalog.yaml, and opens a PR if anything
|
||||
# changed.
|
||||
# 2. `--discover`: reports SKUs present in the API but absent from the
|
||||
# catalog (filtered to serviceCategory values already curated).
|
||||
# If new SKUs are found, opens a Gitea issue listing them by category
|
||||
# for manual review.
|
||||
#
|
||||
# Token:
|
||||
# Uses the auto-provisioned secrets.GITHUB_TOKEN (Gitea Actions provides this
|
||||
# per-run, scoped to this repo, GitHub-Actions-compatible). No manual secret
|
||||
# configuration required. The explicit `permissions:` block below grants the
|
||||
# scopes needed to push a branch, open a PR, and open an issue.
|
||||
name: SKU Catalog Refresh
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 9 1 * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
refresh-and-discover:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Python
|
||||
run: |
|
||||
apt-get update -qq
|
||||
apt-get install -y --no-install-recommends python3 python3-requests python3-yaml jq
|
||||
python3 --version
|
||||
|
||||
- name: Refresh prices from Oracle API
|
||||
id: refresh
|
||||
run: |
|
||||
python3 tools/refresh_sku_catalog.py --refresh --diff 2>&1 \
|
||||
| tee /tmp/refresh.log
|
||||
if git diff --quiet kb/pricing/oci-sku-catalog.yaml; then
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "changed=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Discover missing SKUs
|
||||
id: discover
|
||||
run: |
|
||||
python3 tools/refresh_sku_catalog.py --discover -v 2>&1 \
|
||||
| tee /tmp/discover.log
|
||||
NEW_COUNT=$(grep -oE '^[0-9]+ SKUs present in API' /tmp/discover.log \
|
||||
| head -1 | awk '{print $1}' || echo "0")
|
||||
echo "new_count=${NEW_COUNT:-0}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload logs as artifact
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: sku-refresh-logs
|
||||
path: |
|
||||
/tmp/refresh.log
|
||||
/tmp/discover.log
|
||||
retention-days: 90
|
||||
|
||||
- name: Open PR with price updates
|
||||
if: steps.refresh.outputs.changed == 'true'
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITEA_SERVER: ${{ github.server_url }}
|
||||
GITEA_REPO: ${{ github.repository }}
|
||||
run: |
|
||||
DATE=$(date -u +%Y-%m-%d)
|
||||
BRANCH="automation/sku-refresh-${DATE}"
|
||||
|
||||
git config user.name "sku-refresh-bot"
|
||||
git config user.email "sku-refresh@automation.local"
|
||||
git checkout -b "$BRANCH"
|
||||
git add kb/pricing/oci-sku-catalog.yaml
|
||||
git commit -m "chore(pricing): monthly SKU catalog refresh (${DATE})
|
||||
|
||||
Automated refresh from Oracle public pricing API.
|
||||
See workflow artifact 'sku-refresh-logs' for the diff."
|
||||
|
||||
# Push using token auth
|
||||
REMOTE=$(echo "$GITEA_SERVER/$GITEA_REPO.git" \
|
||||
| sed "s#https://#https://sku-refresh-bot:${GITEA_TOKEN}@#")
|
||||
git push "$REMOTE" "$BRANCH"
|
||||
|
||||
# Open PR via Gitea API
|
||||
OWNER=$(echo "$GITEA_REPO" | cut -d/ -f1)
|
||||
REPO=$(echo "$GITEA_REPO" | cut -d/ -f2)
|
||||
curl -sS -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_SERVER}/api/v1/repos/${OWNER}/${REPO}/pulls" \
|
||||
-d "$(jq -n \
|
||||
--arg title "chore(pricing): monthly SKU refresh ${DATE}" \
|
||||
--arg head "$BRANCH" \
|
||||
--arg base "main" \
|
||||
--arg body "$(printf 'Automated refresh — [refresh log artifact](../../actions).\n\n```\n%s\n```' \
|
||||
"$(tail -40 /tmp/refresh.log)")" \
|
||||
'{title:$title, head:$head, base:$base, body:$body}')"
|
||||
|
||||
- name: Open issue for new SKUs
|
||||
if: steps.discover.outputs.new_count != '0'
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITEA_SERVER: ${{ github.server_url }}
|
||||
GITEA_REPO: ${{ github.repository }}
|
||||
NEW_COUNT: ${{ steps.discover.outputs.new_count }}
|
||||
run: |
|
||||
DATE=$(date -u +%Y-%m-%d)
|
||||
OWNER=$(echo "$GITEA_REPO" | cut -d/ -f1)
|
||||
REPO=$(echo "$GITEA_REPO" | cut -d/ -f2)
|
||||
|
||||
BODY=$(printf '## %s new SKUs detected in Oracle API\n\n**Detected:** %s\n\nThese SKUs are present in the Oracle public pricing API but not yet in `kb/pricing/oci-sku-catalog.yaml`. Filter: serviceCategory values already represented in our catalog (so only relevant families show up).\n\n### Full listing\n\n```\n%s\n```\n\n### Next step\n\nReview and add relevant entries to `kb/pricing/oci-sku-catalog.yaml` under the appropriate category block. After merging, prices will be picked up automatically on the next monthly refresh.\n' \
|
||||
"$NEW_COUNT" "$DATE" "$(cat /tmp/discover.log)")
|
||||
|
||||
curl -sS -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_SERVER}/api/v1/repos/${OWNER}/${REPO}/issues" \
|
||||
-d "$(jq -n \
|
||||
--arg title "SKU catalog: ${NEW_COUNT} new SKUs to review (${DATE})" \
|
||||
--arg body "$BODY" \
|
||||
'{title:$title, body:$body, labels:["automation","sku-catalog"]}')"
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## SKU Refresh Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Catalog changed: ${{ steps.refresh.outputs.changed }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- New SKUs discovered: ${{ steps.discover.outputs.new_count }}" >> $GITHUB_STEP_SUMMARY
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,9 +1,11 @@
|
||||
.venv/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
output/
|
||||
*.pptx
|
||||
!examples/sample-output/*.pptx
|
||||
!templates/Oracle_PPT-template_FY26.pptx
|
||||
|
||||
# OCI Toolkit binary (download from Oracle, don't commit)
|
||||
kb/diagram/OCI Library.xml
|
||||
@@ -31,3 +33,4 @@ examples/*.yaml
|
||||
|
||||
# Exported PDFfiles
|
||||
examples/*.pdf
|
||||
examples/*.xlsx
|
||||
|
||||
45
AGENTS.md
45
AGENTS.md
@@ -85,32 +85,39 @@ DEFINE (Ideate → Validate → Plan) → DESIGN (Current → Future → Confi
|
||||
|
||||
Phase details in `docs/` — skill references them via progressive disclosure.
|
||||
|
||||
## Environment Setup (MANDATORY before running tools)
|
||||
|
||||
```bash
|
||||
make venv && source .venv/bin/activate
|
||||
```
|
||||
|
||||
The Makefile auto-detects the best available Python (3.12 > 3.11 > 3.10 > python3).
|
||||
**Always use `make <target>` to run tools.** For custom specs, activate the venv first.
|
||||
|
||||
### Codex sandbox note
|
||||
|
||||
This project ships `.codex/config.toml` which enables `network_access = true`
|
||||
for the workspace-write sandbox. This is required so `make venv` can reach
|
||||
PyPI. If you see `No matching distribution found for pyyaml`, the config file
|
||||
is missing or Codex is ignoring it — re-open the project from its root so
|
||||
Codex loads `.codex/config.toml`.
|
||||
|
||||
## Running Tools
|
||||
|
||||
```bash
|
||||
# Generate slide deck (default output)
|
||||
# Standard targets (recommended)
|
||||
make deck # slide deck with sample spec
|
||||
make diagram # architecture diagram
|
||||
make full # all outputs (pptx + drawio + docx + xlsx + pdf)
|
||||
make validate # WA validation
|
||||
make lint # check YAML syntax
|
||||
make venv # create/update virtual environment
|
||||
|
||||
# Custom specs (activate venv first)
|
||||
python tools/oci_deck_gen.py --spec examples/proposal-spec.yaml --output proposal.pptx
|
||||
|
||||
# Generate customer-facing PDF (branded, no internal KB refs)
|
||||
python tools/oci_pdf_gen.py --spec examples/proposal-spec.yaml --output proposal.pdf
|
||||
|
||||
# Generate diagram
|
||||
python tools/oci_diagram_gen.py --spec examples/diagram-spec.yaml --output arch.drawio
|
||||
|
||||
# Run WA validation
|
||||
python scripts/validate-architecture.py \
|
||||
--profile examples/sample-workload-profile.yaml \
|
||||
--architecture examples/sample-architecture.yaml \
|
||||
--output scorecard.yaml
|
||||
|
||||
# Output orchestrator (multiple formats at once)
|
||||
python tools/oci_output.py --spec examples/proposal-spec.yaml --format full --output-dir output/
|
||||
|
||||
# Build automation
|
||||
make help # show all commands
|
||||
make full # generate all outputs
|
||||
make validate # run WA validation
|
||||
make lint # check YAML syntax
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
|
||||
110
CLAUDE.md
110
CLAUDE.md
@@ -37,7 +37,9 @@ AI skill aligned with Oracle ECAL framework (Define → Design → Deliver) that
|
||||
│ │ ├── networking-basic.yaml
|
||||
│ │ └── (dirs: database-ha/, database-dr/, networking-hub-spoke/, etc.)
|
||||
│ ├── sizing/ # CPU conversion ratios, IOPS, scaling rules
|
||||
│ ├── pricing/ # Simplified pricing for estimation
|
||||
│ ├── pricing/ # Auto-refreshed from Oracle public pricing API
|
||||
│ │ ├── oci-sku-catalog.yaml # 200+ OCI SKUs across 20 categories (BOM source of truth)
|
||||
│ │ └── compute.yaml # Shape-level estimation pricing
|
||||
│ ├── competitive/ # AWS/Azure/GCP service mapping
|
||||
│ ├── well-architected/ # 5-pillar WA Framework checklists
|
||||
│ ├── compatibility/ # Feature matrices (ADB, etc.)
|
||||
@@ -47,7 +49,9 @@ AI skill aligned with Oracle ECAL framework (Define → Design → Deliver) that
|
||||
│ ├── oci_deck_gen.py # .pptx slide deck generator (DEFAULT output)
|
||||
│ ├── oci_pdf_gen.py # .pdf customer-facing document (branded, no internal refs)
|
||||
│ ├── oci_diagram_gen.py # .drawio diagram generator
|
||||
│ ├── oci_bom_gen.py # .xlsx Bill of Materials generator (SA tool)
|
||||
│ ├── oci_output.py # Output orchestrator
|
||||
│ ├── refresh_sku_catalog.py # SKU catalog refresh from Oracle pricing API
|
||||
│ └── refresh_arch_catalog.py # Architecture Center catalog refresh tool
|
||||
├── scripts/ # Validation and utilities
|
||||
│ └── validate-architecture.py # WA validation engine
|
||||
@@ -72,7 +76,8 @@ AI skill aligned with Oracle ECAL framework (Define → Design → Deliver) that
|
||||
│ ├── handover-document.yaml # DELIVER: Implementation handover
|
||||
│ ├── go-live-checklist.yaml # DELIVER: Pre-cutover verification
|
||||
│ ├── success-criteria.yaml # DELIVER: Post go-live metrics
|
||||
│ └── lessons-learned.yaml # DELIVER: Engagement retrospective
|
||||
│ ├── lessons-learned.yaml # DELIVER: Engagement retrospective
|
||||
│ └── bom-spec.yaml # SA TOOL: BOM input spec template
|
||||
├── codex/ # Codex setup guide (README only)
|
||||
└── examples/ # Example specs and generated outputs
|
||||
```
|
||||
@@ -105,38 +110,44 @@ doc only ← technical doc without slides
|
||||
deliver ← handover + go-live checklist + success criteria
|
||||
```
|
||||
|
||||
## Running Tools
|
||||
## Environment Setup
|
||||
|
||||
Before running ANY Python tool, ensure dependencies are installed:
|
||||
|
||||
```bash
|
||||
# Generate slide deck (default output)
|
||||
make venv && source .venv/bin/activate
|
||||
```
|
||||
|
||||
The Makefile auto-detects the best available Python (3.12 > 3.11 > 3.10 > python3).
|
||||
**Always use `make <target>` to run tools** — this guarantees the correct Python with all dependencies.
|
||||
|
||||
## Running Tools
|
||||
|
||||
Prefer `make` targets. For custom specs, activate the venv first (`source .venv/bin/activate`), then use `python`:
|
||||
|
||||
```bash
|
||||
# Standard targets (recommended)
|
||||
make deck # slide deck with sample spec
|
||||
make diagram # architecture diagram
|
||||
make full # all outputs (pptx + drawio + docx + xlsx + pdf)
|
||||
make validate # WA validation
|
||||
make lint # check YAML syntax
|
||||
make venv # create/update virtual environment
|
||||
make freshness # check KB freshness
|
||||
|
||||
# Custom specs (activate venv first)
|
||||
python tools/oci_deck_gen.py --spec examples/proposal-spec.yaml --output proposal.pptx
|
||||
|
||||
# Generate customer-facing PDF (branded, no internal KB refs)
|
||||
python tools/oci_pdf_gen.py --spec examples/proposal-spec.yaml --output proposal.pdf
|
||||
python tools/oci_pdf_gen.py --spec examples/proposal-spec.yaml --output proposal.pdf --diagram arch.png
|
||||
|
||||
# Generate diagram
|
||||
python tools/oci_bom_gen.py --spec examples/bom-spec.yaml --output customer-bom.xlsx
|
||||
python tools/oci_diagram_gen.py --spec examples/diagram-spec.yaml --output arch.drawio
|
||||
|
||||
# Run WA validation
|
||||
python scripts/validate-architecture.py \
|
||||
--profile examples/sample-workload-profile.yaml \
|
||||
--architecture examples/sample-architecture.yaml \
|
||||
--output scorecard.yaml
|
||||
|
||||
# Output orchestrator (multiple formats at once)
|
||||
python tools/oci_output.py --spec examples/proposal-spec.yaml --format full --output-dir output/
|
||||
|
||||
# Refresh Architecture Center catalog
|
||||
python tools/refresh_arch_catalog.py --whats-new # crawl What's New pages
|
||||
python tools/refresh_arch_catalog.py --url <url> # add single entry
|
||||
# KB maintenance (activate venv first)
|
||||
python tools/refresh_sku_catalog.py --refresh # update all prices
|
||||
python tools/refresh_sku_catalog.py --refresh --diff # update + show changes
|
||||
python tools/refresh_sku_catalog.py --validate # check for stale prices
|
||||
python tools/refresh_arch_catalog.py --whats-new # crawl What's New pages
|
||||
python tools/refresh_arch_catalog.py --validate # validate catalog
|
||||
|
||||
# Build automation
|
||||
make help # show all commands
|
||||
make full # generate all outputs
|
||||
make validate # run WA validation
|
||||
make lint # check YAML syntax
|
||||
```
|
||||
|
||||
## Key Principles
|
||||
@@ -148,12 +159,51 @@ make lint # check YAML syntax
|
||||
- **KB is the moat** — field experience, not documentation regurgitation
|
||||
- **ECAL-aligned** — Define → Design → Deliver with iterative checkpoints
|
||||
|
||||
## Coding Guidelines
|
||||
|
||||
### 1. Think Before Coding
|
||||
Don't assume. Don't hide confusion. Surface tradeoffs.
|
||||
- State your assumptions explicitly. If uncertain, ask.
|
||||
- If multiple interpretations exist, present them — don't pick silently.
|
||||
- If a simpler approach exists, say so. Push back when warranted.
|
||||
- If something is unclear, stop. Name what's confusing. Ask.
|
||||
|
||||
### 2. Simplicity First
|
||||
Minimum code that solves the problem. Nothing speculative.
|
||||
- No features beyond what was asked.
|
||||
- No abstractions for single-use code.
|
||||
- No "flexibility" or "configurability" that wasn't requested.
|
||||
- No error handling for impossible scenarios.
|
||||
- If you write 200 lines and it could be 50, rewrite it.
|
||||
|
||||
### 3. Surgical Changes
|
||||
Touch only what you must. Clean up only your own mess.
|
||||
- Don't "improve" adjacent code, comments, or formatting.
|
||||
- Don't refactor things that aren't broken.
|
||||
- Match existing style, even if you'd do it differently.
|
||||
- If you notice unrelated dead code, mention it — don't delete it.
|
||||
- Remove imports/variables/functions that YOUR changes made unused.
|
||||
- Every changed line should trace directly to the user's request.
|
||||
|
||||
### 4. Goal-Driven Execution
|
||||
Define success criteria. Loop until verified.
|
||||
- "Add validation" → write tests for invalid inputs, then make them pass.
|
||||
- "Fix the bug" → write a test that reproduces it, then make it pass.
|
||||
- "Refactor X" → ensure tests pass before and after.
|
||||
- For multi-step tasks, state a brief plan with verification steps.
|
||||
|
||||
## Welcome Flow
|
||||
|
||||
When the user starts a conversation without providing discovery notes or a specific request (e.g., a greeting like "hola", "hey", or empty context), present the welcome message and capability menu defined in `SKILL.md` § Welcome Flow. Specifically:
|
||||
When the user starts a conversation without providing discovery notes or a specific request (e.g., a greeting like "hola", "hey", or empty context):
|
||||
|
||||
1. Show the welcome banner and numbered capability menu from SKILL.md
|
||||
2. Follow the behavior rules for each option (1-10)
|
||||
3. After completing any task, offer the next-step menu (A-E)
|
||||
**MANDATORY:** Use the `Read` tool to open `SKILL.md` and read the entire `## Welcome Flow` section **before** showing anything to the user. Reproduce the welcome banner and the 14-option capability menu **verbatim** from that file. Do NOT paraphrase, reorder, summarize, translate, or reconstruct the menu from memory, folder structure, or prior conversations. If `SKILL.md` cannot be read for any reason, tell the user instead of improvising a menu.
|
||||
|
||||
**Pre-flight check (also defined in SKILL.md):** Before showing the welcome message, run `make kb-check 2>/dev/null`. If `stale_count > 0`, follow the banner-and-prompt logic in SKILL.md § Welcome Flow → Pre-flight. If the tool errors, silently skip the banner — never block the user.
|
||||
|
||||
Then:
|
||||
|
||||
1. Show the welcome banner and numbered capability menu exactly as defined in SKILL.md (14 options across DESIGN & PROPOSE, VALIDATE & CHECK, STRATEGY & BUSINESS, KNOWLEDGE BASE, ECAL GOVERNANCE, SA TOOLS)
|
||||
2. Follow the behavior rules in SKILL.md for each option (1-14)
|
||||
3. After completing any task, offer the next-step menu (A-E) as defined in SKILL.md
|
||||
4. If the user sends discovery notes directly, skip the menu and go straight to full proposal flow
|
||||
5. If the user asks a specific question, skip the menu and answer directly
|
||||
|
||||
43
Makefile
43
Makefile
@@ -1,8 +1,15 @@
|
||||
# OCI Deal Accelerator — Build Automation
|
||||
|
||||
.PHONY: help install test validate example diagram deck full clean lint codex-package update-icons
|
||||
.PHONY: help install test validate example diagram deck full clean lint codex-package update-icons freshness freshness-refresh sync-skill sku-discover
|
||||
|
||||
PYTHON ?= python3.12
|
||||
# Use venv if present, otherwise find best available python3
|
||||
ifneq (,$(wildcard .venv/bin/python))
|
||||
PYTHON ?= .venv/bin/python
|
||||
else ifneq (,$(shell command -v python3.12 2>/dev/null))
|
||||
PYTHON ?= python3.12
|
||||
else
|
||||
PYTHON ?= python3
|
||||
endif
|
||||
SPEC_DIR = examples
|
||||
OUTPUT_DIR = examples/sample-output
|
||||
|
||||
@@ -10,7 +17,16 @@ help: ## Show this help
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
|
||||
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
install: ## Install Python dependencies
|
||||
VENV_PYTHON := $(shell command -v python3.12 2>/dev/null || command -v python3.11 2>/dev/null || command -v python3.10 2>/dev/null || echo python3)
|
||||
|
||||
venv: ## Create virtual environment and install dependencies
|
||||
@echo "Using $(VENV_PYTHON) to create venv..."
|
||||
$(VENV_PYTHON) -m venv .venv
|
||||
.venv/bin/pip install --upgrade pip
|
||||
.venv/bin/pip install -r requirements.txt
|
||||
@echo "Virtual environment ready. Run: source .venv/bin/activate"
|
||||
|
||||
install: ## Install Python dependencies (system-wide)
|
||||
pip install -r requirements.txt
|
||||
|
||||
validate: ## Validate imports and configs
|
||||
@@ -62,8 +78,25 @@ clean: ## Remove generated output files
|
||||
rm -f examples/sample-output/*.xlsx
|
||||
rm -f examples/sample-output/*.docx
|
||||
|
||||
lint: ## Check YAML files for syntax errors
|
||||
lint: ## Check YAML files for syntax errors and validate SKILL.md sync
|
||||
@echo "Checking YAML files..."
|
||||
@find kb/ config/ examples/ -name '*.yaml' -exec $(PYTHON) -c \
|
||||
"import yaml, sys; yaml.safe_load(open(sys.argv[1]))" {} \; \
|
||||
"import yaml, sys; list(yaml.safe_load_all(open(sys.argv[1])))" {} \; \
|
||||
-print 2>&1 | grep -v "^$$" || echo "All YAML files valid."
|
||||
@echo "Checking SKILL.md sync..."
|
||||
@$(PYTHON) scripts/sync-skill.py --check
|
||||
|
||||
sync-skill: ## Regenerate .agents/skills/oci-deal-accelerator/SKILL.md from root SKILL.md
|
||||
@$(PYTHON) scripts/sync-skill.py
|
||||
|
||||
freshness: ## Report stale KB files (informational, never fails)
|
||||
-@$(PYTHON) tools/kb_freshness.py --check
|
||||
|
||||
kb-check: ## KB freshness JSON (used by skill welcome-flow pre-flight)
|
||||
@$(PYTHON) tools/kb_freshness.py --check --json
|
||||
|
||||
freshness-refresh: ## Run refresh tools for stale KB files that support automation
|
||||
@$(PYTHON) tools/kb_freshness.py --auto-refresh
|
||||
|
||||
sku-discover: ## Report SKUs present in Oracle API but missing from oci-sku-catalog.yaml
|
||||
@$(PYTHON) tools/refresh_sku_catalog.py --discover
|
||||
|
||||
94
README.md
94
README.md
@@ -14,6 +14,40 @@ What normally takes an SA days of work (structuring notes, designing architectur
|
||||
- **Multi-cloud aware** — supports hybrid/multi-cloud diagrams (AWS, Azure, GCP icons) and considers options like ADB Multicloud before recommending full migration
|
||||
- **End-to-end coverage** — from discovery notes to go-live checklist, not just the architecture slide
|
||||
|
||||
## New user? Start here
|
||||
|
||||
The skill runs as a hosted MCP server. Connect once from your LLM client, sign in with Oracle SSO, and the tools are ready.
|
||||
|
||||
**1. Add the MCP server to your client:**
|
||||
|
||||
| Client | How |
|
||||
|---|---|
|
||||
| **Claude Code** | `claude mcp add --transport http oci-deal-accelerator "https://mcp.tech-lad.com/deal-accelerator/mcp/"` |
|
||||
| **Codex** | `codex mcp add oci-deal-accelerator --url "https://mcp.tech-lad.com/deal-accelerator/mcp/"` |
|
||||
| **Cursor** | Settings (Ctrl+Shift+J) → MCP → Add new MCP server → Name: `oci-deal-accelerator`, Type: `streamable-http`, URL: `https://mcp.tech-lad.com/deal-accelerator/mcp/` |
|
||||
| **Claude Desktop** | Add to `claude_desktop_config.json`: `{ "mcpServers": { "oci-deal-accelerator": { "transport": "http", "url": "https://mcp.tech-lad.com/deal-accelerator/mcp/" } } }` |
|
||||
| **Windsurf** | Settings → Cascade → MCP → Manual config: `{ "oci-deal-accelerator": { "serverUrl": "https://mcp.tech-lad.com/deal-accelerator/sse/" } }` |
|
||||
|
||||
**2. Trigger the connection** — type `/mcp` in Claude Code or Codex, or open any tool in Cursor / Claude Desktop / Windsurf. Your browser opens automatically.
|
||||
|
||||
**3. Pick one of two options in the browser:**
|
||||
- **Sign in with Oracle SSO** — for existing users
|
||||
- **Create a new account** — for new users (see step 4)
|
||||
|
||||
**4. New users — create an account** by clicking "Create a new account". This opens an OCI self-registration form (oracle.com emails only). Tips:
|
||||
- Use your full Oracle email as User ID (e.g. `name@oracle.com`)
|
||||
- Password must be 12+ chars, with an uppercase letter, a number, and a special character
|
||||
- Password must NOT contain your name or username
|
||||
|
||||
**5. Verify your email**, then return to the browser and click **Sign in with Oracle SSO**.
|
||||
|
||||
**6. Done.** The MCP tools are now available in your client.
|
||||
|
||||
### Connection URLs
|
||||
|
||||
- **MCP (HTTP streamable):** `https://mcp.tech-lad.com/deal-accelerator/mcp/`
|
||||
- **SSE (Windsurf only):** `https://mcp.tech-lad.com/deal-accelerator/sse/`
|
||||
|
||||
## What It Produces
|
||||
|
||||
From unstructured input (meeting notes, emails, Slack threads), the skill generates:
|
||||
@@ -86,31 +120,27 @@ Any SA can contribute knowledge to the skill. The KB lives in `kb/` as editable
|
||||
| **OCI service info** | `kb/services/<service>.yaml` | Create or edit the service YAML |
|
||||
| **Architecture pattern** | `kb/patterns/` | Add YAML following existing format |
|
||||
| **Architecture Center reference** | `kb/architecture-center/catalog.yaml` | `python tools/refresh_arch_catalog.py --url <url>` |
|
||||
| **Updated pricing** | `kb/pricing/<category>.yaml` | Edit with data from [OCI Price List](https://www.oracle.com/cloud/price-list/) |
|
||||
| **Updated pricing** | `kb/pricing/oci-sku-catalog.yaml` (SKUs) or `kb/pricing/compute.yaml` (shapes) | `python tools/refresh_sku_catalog.py --refresh` (SKUs) or `--refresh-domain compute` (shapes). Both auto-pull from the Oracle public pricing API. |
|
||||
| **Feature compatibility** | `kb/compatibility/adb-feature-matrix.yaml` | Edit the matrix, mark `verified_in_field: true` |
|
||||
| **Competitive comparison** | `kb/competitive/` | Add or edit YAML with real pros AND cons |
|
||||
|
||||
**Fastest path**: if you hit something in an engagement that another SA should know about, use menu option 11 (Report a field finding) — the skill walks you through the format and adds it to the tracker automatically.
|
||||
|
||||
### OCI Pricing (13 categories)
|
||||
### OCI Pricing
|
||||
|
||||
Comprehensive pricing from the [OCI Price List](https://www.oracle.com/cloud/price-list/) covering compute, database, storage, networking, AI/ML, containers, integration, observability, developer, analytics, hybrid/VMware, and security services. Source date: 2025-09-11.
|
||||
All pricing is auto-refreshed from the [Oracle public pricing API](https://apexapps.oracle.com/pls/apex/cetools/api/v1/products/?currencyCode=USD). No manually maintained pricing files.
|
||||
|
||||
```
|
||||
kb/pricing/
|
||||
├── compute.yaml # VMs, bare metal, GPU (B200/B300/H200/H100/A100/L40S)
|
||||
├── database.yaml # ADB (ECPU), DBCS, ExaCS, MySQL, PostgreSQL, NoSQL, Redis
|
||||
├── storage.yaml # Block, object, file, data transfer
|
||||
├── networking.yaml # LB, NLB, FastConnect, DNS, egress
|
||||
├── ai-ml.yaml # GenAI, Data Science, Vision, Speech, Digital Assistant
|
||||
├── containers-serverless.yaml # OKE, Functions, Container Instances
|
||||
├── integration.yaml # OIC, API Mgmt, Streaming, Queue, GoldenGate
|
||||
├── observability.yaml # Monitoring, Logging, APM, DR, Email
|
||||
├── developer.yaml # APEX, Visual Builder, DevOps, Blockchain
|
||||
├── analytics.yaml # OAC, Essbase, Big Data, Data Flow
|
||||
├── hybrid-vmware.yaml # OCVS, Compute C@C, Managed Mac, Roving Edge
|
||||
├── security.yaml # Access Governance, Vault, Cloud Guard
|
||||
└── pricing-models.yaml # PAYG, UCM, Reserved, BYOL
|
||||
├── oci-sku-catalog.yaml # 200+ SKUs across 20 categories — single source of truth
|
||||
│ Refresh: python tools/refresh_sku_catalog.py --refresh
|
||||
└── compute.yaml # Shape-level estimation pricing (VMs, BM, GPU)
|
||||
Refresh: python tools/refresh_sku_catalog.py --refresh-domain compute
|
||||
|
||||
kb/field-knowledge/pricing-knowledge.yaml
|
||||
# Stable pricing context: billing models, BYOL rules,
|
||||
free tiers, service nuances, hyperscaler comparisons.
|
||||
Non-numeric — no refresh needed.
|
||||
```
|
||||
|
||||
### DBExpert Database Services Catalog
|
||||
@@ -135,6 +165,34 @@ During **Phase 2 (DESIGN)**, the skill automatically matches the proposed archit
|
||||
python tools/refresh_arch_catalog.py --whats-new # crawl What's New pages
|
||||
python tools/refresh_arch_catalog.py --url <url> # add a single entry
|
||||
python tools/refresh_arch_catalog.py --validate # validate catalog integrity
|
||||
python tools/refresh_arch_catalog.py --check-links # check for broken URLs (404s, redirects)
|
||||
```
|
||||
|
||||
### KB Health & Freshness
|
||||
|
||||
The KB is automatically monitored for staleness and broken links:
|
||||
|
||||
| Check | How | When |
|
||||
|---|---|---|
|
||||
| **Broken links** | `python tools/refresh_arch_catalog.py --check-links` | Weekly (CI), or on demand |
|
||||
| **Stale prices** | `python tools/refresh_sku_catalog.py --validate` | Weekly (CI), or on demand |
|
||||
| **KB freshness** | `python tools/kb_freshness.py --check` | On skill startup (pre-flight) |
|
||||
| **Diagram quality** | `python scripts/validate-diagram.py <file.drawio>` | After every diagram generation |
|
||||
|
||||
**Automated CI/CD:**
|
||||
- **Deploy workflow** (`.gitea/workflows/deploy.yaml`) — auto-deploys to MCP server on every push to `main`
|
||||
- **KB health workflow** (`.gitea/workflows/kb-health.yaml`) — runs every Monday 8am UTC, checks all catalog URLs and SKU freshness, reports broken links as artifacts
|
||||
|
||||
To run KB health manually:
|
||||
```bash
|
||||
# Check all 123 Architecture Center URLs for 404s
|
||||
python tools/refresh_arch_catalog.py --check-links
|
||||
|
||||
# Fix broken links: re-crawl What's New for updated URLs
|
||||
python tools/refresh_arch_catalog.py --whats-new
|
||||
|
||||
# Refresh stale pricing from Oracle API
|
||||
python tools/refresh_sku_catalog.py --refresh --diff
|
||||
```
|
||||
|
||||
### Feature Compatibility Matrix
|
||||
@@ -300,12 +358,16 @@ python tools/oci_bizcase_gen.py --spec business-case.yaml --output business-case
|
||||
# Architecture diagram
|
||||
python tools/oci_diagram_gen.py --spec examples/diagram-spec.yaml --output arch.drawio
|
||||
|
||||
# Validate diagram quality (icon sizes, overlaps, container overflow)
|
||||
python scripts/validate-diagram.py arch.drawio
|
||||
|
||||
# Output orchestrator (multiple formats at once)
|
||||
python tools/oci_output.py --spec examples/proposal-spec.yaml --format full --output-dir output/
|
||||
|
||||
# Architecture Center catalog
|
||||
python tools/refresh_arch_catalog.py --validate
|
||||
python tools/refresh_arch_catalog.py --whats-new
|
||||
python tools/refresh_arch_catalog.py --check-links
|
||||
|
||||
# Feature compatibility
|
||||
python tools/feature_matrix_cli.py check "Auto Scaling" adb_s 23ai
|
||||
|
||||
436
SKILL.md
436
SKILL.md
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: OCI Deal Accelerator
|
||||
name: oci-deal-accelerator
|
||||
description: Compresses the OCI Solutions Architect's cycle from customer discovery to architecture proposal and delivery handover. Aligned with Oracle ECAL framework (Define, Design, Deliver). Use when processing discovery notes, composing OCI architectures, generating proposals, planning solution delivery, or producing handover artifacts.
|
||||
---
|
||||
|
||||
@@ -15,6 +15,55 @@ You follow the **Oracle ECAL framework** (Define → Design → Deliver) to prod
|
||||
|
||||
When the user starts a conversation without providing discovery notes or a specific request, present the welcome message and capability menu.
|
||||
|
||||
### Pre-flight checks
|
||||
|
||||
Run these checks silently **before** showing the welcome message. **CRITICAL:** Never show command execution, tool output, or errors to the user. If any check fails, silently skip it and proceed to the welcome message. These checks are informational — they NEVER block the user.
|
||||
|
||||
#### Check 1: KB changelog banner
|
||||
|
||||
Read the file `kb/CHANGELOG.md` and extract the **most recent date and first bullet point**. If the file exists and has entries, prepend a one-line banner above the welcome message:
|
||||
|
||||
```
|
||||
📢 KB updated (<date>): <first bullet summary>
|
||||
```
|
||||
|
||||
Example: `📢 KB updated (Apr 14): Diagram generator calibrated from 37 Oracle ref architectures`
|
||||
|
||||
If the file is missing or empty, skip — no banner.
|
||||
|
||||
#### Check 2: Local repo updates (git users only)
|
||||
|
||||
Run `git fetch --dry-run origin main 2>/dev/null`. If the output contains any text (meaning there are remote commits not yet pulled), prepend this banner:
|
||||
|
||||
```
|
||||
📢 KB updates available — run `git pull` to get latest prices and fixes.
|
||||
```
|
||||
|
||||
If the command fails (not a git repo, no network, MCP deployment), silently skip. This check is only relevant for users running the skill from a local git clone.
|
||||
|
||||
#### Check 3: KB freshness
|
||||
|
||||
Run `make kb-check 2>/dev/null` and parse the JSON output. Behavior:
|
||||
|
||||
- **`stale_count == 0`** → no banner.
|
||||
- **`stale_count > 0` and at least one file has `refreshable: true`** → prepend banner and ask inline:
|
||||
|
||||
```
|
||||
⚠️ KB freshness: <N> file(s) outdated (oldest: <file> — <age_days>d).
|
||||
<M> can be auto-refreshed. Refresh now? [y/N]
|
||||
```
|
||||
|
||||
- `y` / `yes` / `sí` → run `make freshness-refresh`, then show menu.
|
||||
- Anything else → show menu with one-line reminder: `⚠️ <N> KB file(s) stale — run make freshness-refresh later.`
|
||||
|
||||
- **`stale_count > 0` but no `refreshable: true`** → non-blocking info banner, then show menu directly:
|
||||
|
||||
```
|
||||
⚠️ KB freshness: <N> file(s) need manual review (oldest: <file> — <age_days>d).
|
||||
```
|
||||
|
||||
If `make kb-check` errors out (exit ≠ 0, missing make, missing Python, missing tool), **silently skip** — no error output, no banner, no mention of failure.
|
||||
|
||||
### Welcome Message
|
||||
|
||||
```
|
||||
@@ -59,6 +108,11 @@ Present these options as a compact numbered list. Each option has a bold title f
|
||||
─────────────────
|
||||
12. 📊 ECAL readiness score — *60-artefact gap analysis*
|
||||
|
||||
SA TOOLS
|
||||
─────────────────
|
||||
13. 📦 BOM generator — *services + quantities → .xlsx Bill of Materials*
|
||||
14. 📤 BOM for AppCA — *BOM → .xlsx ready to import into AppCA*
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Pick a number, or just describe what you need.
|
||||
```
|
||||
@@ -80,74 +134,13 @@ Pick a number, or just describe what you need.
|
||||
- Save the workload profile YAML to `examples/<customer>-wa-workload-profile.yaml`
|
||||
6. After the scorecard, offer next actions
|
||||
|
||||
**WA Review Output Format:**
|
||||
|
||||
The WA review MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML files saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
|
||||
|
||||
```
|
||||
══════════════════════════════════════════════════════
|
||||
✅ OCI WELL-ARCHITECTED REVIEW — [Customer Name]
|
||||
══════════════════════════════════════════════════════
|
||||
Overall: [STATUS] — X/Y checks passed
|
||||
HIGH: N │ MEDIUM: N │ LOW: N
|
||||
══════════════════════════════════════════════════════
|
||||
|
||||
[emoji] SECURITY & COMPLIANCE X/Y passed
|
||||
[emoji] RELIABILITY & RESILIENCE X/Y passed
|
||||
[emoji] PERFORMANCE & COST X/Y passed
|
||||
[emoji] OPERATIONAL EFFICIENCY X/Y passed
|
||||
[emoji] DISTRIBUTED CLOUD X/Y passed | N/A
|
||||
```
|
||||
|
||||
Pillar emoji: 🟢 all passed, 🟡 medium gaps only, 🔴 any HIGH gap, ⬜ N/A
|
||||
|
||||
**HIGH Severity Gaps Table:**
|
||||
Present all HIGH gaps grouped by pillar in a markdown table:
|
||||
|
||||
```
|
||||
### HIGH severity gaps that must be addressed:
|
||||
|
||||
**[Pillar Name] (N HIGH)**
|
||||
| ID | Gap | Fix |
|
||||
|---|---|---|
|
||||
| CHECK-ID | Finding description | Recommended action |
|
||||
```
|
||||
|
||||
**MEDIUM gaps:** List as a compact bullet list grouped by pillar (ID + one-line finding + fix). Skip the table format to keep it concise.
|
||||
|
||||
**LOW gaps:** Mention count only, list individual items only if ≤ 5.
|
||||
|
||||
**Analysis Section:**
|
||||
After the gap tables, add a "Why so many gaps?" paragraph if total gaps > 20, explaining the root cause (e.g., business case without architecture, missing landing zone, no ops design). This contextualizes the score for the SA.
|
||||
|
||||
**Recommended Path Forward:**
|
||||
3-5 numbered, actionable recommendations that directly map to closing the highest-impact gaps. Reference skill options where applicable (e.g., "Generate the architecture — option 1 or 2").
|
||||
|
||||
**Files Generated:**
|
||||
Always list the files saved at the end of the review:
|
||||
```
|
||||
📁 Files saved:
|
||||
- examples/<customer>-wa-scorecard.yaml
|
||||
- examples/<customer>-wa-architecture.yaml
|
||||
- examples/<customer>-wa-workload-profile.yaml
|
||||
```
|
||||
|
||||
**After WA Review Menu:**
|
||||
```
|
||||
What do you want to do?
|
||||
→ [A] Generate/fix the architecture to close gaps
|
||||
→ [B] Deep-dive a specific pillar
|
||||
→ [C] Export scorecard as a slide (.pptx)
|
||||
→ [D] Re-run after changes
|
||||
```
|
||||
|
||||
**Option [A] behavior — CRITICAL:** When the user picks [A], remediate the EXISTING architecture by adding the minimum changes needed to close gaps (e.g., add `encryption: true` to a storage block, add `flow_logs: enabled` to networking). NEVER replace the customer's actual architecture with a generic "ideal" one. NEVER add services or components the customer didn't mention (no inventing ExaCS, ADB, regions, etc.). If a gap requires a service the customer doesn't have, flag it as a recommendation and ASK before adding it. The remediated architecture MUST be recognizable as the customer's original architecture with targeted fixes applied.
|
||||
**WA Review Output Format:** see [docs/skill/wa-review-format.md](docs/skill/wa-review-format.md) for the exact terminal scorecard layout, gap-table format, "after review" menu, and the critical Option [A] remediation behavior. Read that file before producing the scorecard.
|
||||
- If the user picks **6**, ask: "What feature and deployment type? (e.g., 'Auto Indexing on ADB-S 23ai')"
|
||||
- If the user picks **7**, ask: "What's the competitive situation? (e.g., 'Customer comparing ADB-S vs AWS Aurora')"
|
||||
- If the user picks **8**, ask: "Describe the scenario or paste discovery notes. I'll build the business case. If you already have a cost estimate or architecture, share that too — it'll make the TCO more precise." Then follow the business case flow:
|
||||
1. Parse input into `templates/business-case.yaml` structure
|
||||
2. Identify business drivers and urgency from discovery notes
|
||||
3. Estimate TCO comparison using `kb/pricing/*` and `kb/sizing/*`
|
||||
3. Estimate TCO comparison using `kb/pricing/oci-sku-catalog.yaml` (live SKU prices), `kb/pricing/compute.yaml` (shape-level), `kb/field-knowledge/pricing-knowledge.yaml` (billing models, BYOL rules, free tiers), and `kb/sizing/*`
|
||||
4. Calculate ROI and payback period
|
||||
5. Map value drivers (cost, risk, agility, innovation) with quantified evidence
|
||||
6. Assess migration risks from `kb/field-knowledge/gotchas.yaml` and do-nothing risks
|
||||
@@ -185,84 +178,30 @@ Pick a number, or just describe what you need.
|
||||
- Present the formatted terminal scorecard (primary deliverable)
|
||||
8. Output the ECAL Readiness Scorecard
|
||||
|
||||
**Scoring Model:**
|
||||
Each artefact has a status: ✅ Complete | 🟡 Partial | ❌ Missing | ⬜ Not Applicable (future phase)
|
||||
**Scoring model, readiness levels, and output format:** see [docs/skill/ecal-readiness-format.md](docs/skill/ecal-readiness-format.md) for the scoring weights, the terminal scorecard layout, and the after-scorecard menu. Read that file before producing the scorecard.
|
||||
|
||||
Phase scores are calculated as:
|
||||
- ✅ = 1.0 point, 🟡 = 0.5 point, ❌ = 0 points, ⬜ = excluded from denominator
|
||||
- Phase score = (sum of points / applicable artefacts) × 100%
|
||||
- If the user picks **13**, ask: "What services does the customer need? (e.g., 'ExaCS X11M BYOL 2 DB servers + 4 storage + 128 ECPUs + ADB-S 8 ECPU + 2TB Block Storage + FastConnect 1Gbps'). I'll generate the BOM with only those SKUs."
|
||||
Then follow the BOM generation flow:
|
||||
1. Parse the customer request to identify needed OCI services and quantities
|
||||
2. Match services against `kb/pricing/oci-sku-catalog.yaml` (live, auto-refreshed) to select exact SKUs
|
||||
3. Ask for discount % and contract duration if not specified (default: 0%, 12 months)
|
||||
4. Ask if currency conversion is needed (e.g., USD→BRL with exchange rate and tax)
|
||||
5. Generate the BOM spec YAML and save to the output folder
|
||||
6. Run `tools/oci_bom_gen.py` to produce the .xlsx
|
||||
7. Present a summary table in the terminal showing key totals (monthly, ARR)
|
||||
8. List the files generated
|
||||
|
||||
Overall ECAL Readiness = weighted average:
|
||||
- DEFINE: 25% weight
|
||||
- DESIGN: 50% weight (largest phase, most artefacts)
|
||||
- DELIVER: 25% weight
|
||||
**BOM Output Rules:**
|
||||
- NEVER include "Confidential: Internal ONLY" or any confidentiality marking
|
||||
- ALWAYS include the Oracle Cost Estimator disclaimer at the bottom
|
||||
- Only include SKUs the customer actually requested — never dump the full catalog
|
||||
- Show cost proportions so the customer can see where their spend concentrates
|
||||
- Use Excel formulas (not static values) so the customer can adjust quantities
|
||||
|
||||
**Readiness Levels:**
|
||||
- 🟢 80-100% — Ready to proceed to next phase
|
||||
- 🟡 60-79% — Gaps exist but manageable; proceed with caution
|
||||
- 🟠 40-59% — Significant gaps; address before proceeding
|
||||
- 🔴 0-39% — Major gaps; phase needs substantial work
|
||||
|
||||
**Output Format:**
|
||||
|
||||
The ECAL readiness score MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML file saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
|
||||
|
||||
```
|
||||
══════════════════════════════════════════
|
||||
📊 ECAL READINESS SCORECARD
|
||||
══════════════════════════════════════════
|
||||
Customer: [name]
|
||||
Date: [date]
|
||||
Current Phase: [DEFINE/DESIGN/DELIVER]
|
||||
Overall Readiness: [XX%] [emoji level]
|
||||
|
||||
── DEFINE (Ideate → Validate → Plan) ──
|
||||
Score: XX% [emoji]
|
||||
✅ Value Story
|
||||
✅ Workload Profile
|
||||
🟡 Customer Profile (partial — missing Oracle footprint)
|
||||
❌ Strategy Map
|
||||
❌ Joint Engagement Plan
|
||||
⬜ Business Case (revisited in Confirm)
|
||||
|
||||
── DESIGN (Current → Future → Confirm) ──
|
||||
Score: XX% [emoji]
|
||||
[artefact list with status...]
|
||||
|
||||
── DELIVER (Adopt → Operate → Improve) ──
|
||||
Score: XX% [emoji]
|
||||
[artefact list with status...]
|
||||
|
||||
── TOP 5 GAPS ──
|
||||
1. ❌ [artefact] — [why it matters] — [recommended action]
|
||||
2. ...
|
||||
|
||||
── RECOMMENDED NEXT ACTIONS ──
|
||||
1. [specific action]
|
||||
2. [specific action]
|
||||
3. [specific action]
|
||||
|
||||
── ENGAGEMENT RACI CHECK ──
|
||||
Roles identified: [list]
|
||||
Roles missing: [list]
|
||||
══════════════════════════════════════════
|
||||
```
|
||||
|
||||
**Files Generated:**
|
||||
Always list the files saved at the end of the scorecard:
|
||||
```
|
||||
📁 Files saved:
|
||||
- examples/<customer>-ecal-scorecard.yaml
|
||||
```
|
||||
|
||||
After showing the scorecard, offer:
|
||||
```
|
||||
What do you want to do?
|
||||
→ [A] Fix the top gap now (I'll generate the missing artefact)
|
||||
→ [B] Generate all missing artefacts for current phase
|
||||
→ [C] Export scorecard as a slide (.pptx)
|
||||
→ [D] Re-score after updates
|
||||
```
|
||||
- If the user picks **14**, follow the same flow as option 13 (BOM generator) but generate the output in AppCA import format. AppCA is Oracle's internal deal approval tool. The generated .xlsx has two sheets:
|
||||
- **"Export to AppCA"**: Flat table with columns SKU, QTY, HOURS, MONTHS, DISCOUNT, BURSTABLE — ready to paste/import into AppCA
|
||||
- **"BOM.C1"**: Full BOM detail with product names, metrics, prices, and formulas for cost calculations
|
||||
Run with: `python tools/oci_bom_gen.py --spec <spec>.yaml --output <name>.xlsx --appca`
|
||||
|
||||
- If the user sends discovery notes directly (without picking a number), detect this and go straight to option 1 (full proposal flow).
|
||||
- If the user asks a specific question (e.g., "does ADB-S support vector search?"), detect this and go straight to the relevant capability without showing the menu.
|
||||
@@ -335,6 +274,32 @@ Full tier definitions and artifact matrix: [docs/engagement-tiers.md](docs/engag
|
||||
|
||||
**Step 1 — Ideate:** Parse discovery notes into a **Workload Profile** (`templates/workload-profile.yaml`). Formulate a value hypothesis: "If we [technical action], the customer achieves [business outcome]." Use `kb/patterns/business-patterns.yaml` for proven business-level patterns.
|
||||
|
||||
**Step 1b — Extraction Receipt (MANDATORY).** After parsing discovery notes, present an extraction receipt to the user BEFORE proceeding. This ensures the architecture is built on confirmed facts, not assumptions:
|
||||
```
|
||||
📋 Extraction Receipt
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
From your input I extracted:
|
||||
|
||||
CONFIRMED (explicitly stated):
|
||||
• [field]: [value] — source: "[exact quote or reference from notes]"
|
||||
• [field]: [value] — source: "[exact quote or reference from notes]"
|
||||
|
||||
INFERRED (not stated, derived from context):
|
||||
• [field]: [value] — reason: "[why I inferred this]"
|
||||
|
||||
MISSING (needed but not provided):
|
||||
• [field] — needed for: [which artifact or decision needs it]
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
Confirm, correct, or fill gaps before I proceed.
|
||||
```
|
||||
Rules:
|
||||
- Every field in the workload profile that you populate must appear in either CONFIRMED or INFERRED.
|
||||
- Do NOT proceed to Step 2 until the user confirms the receipt.
|
||||
- If the user provides additional data, update the receipt and re-confirm.
|
||||
- When generating the workload-profile.yaml, tag each field with `source: customer` (confirmed), `source: inferred`, or `source: default` so the SA knows what to validate with the customer.
|
||||
|
||||
**Step 2 — Validate:** Test the hypothesis for SMART criteria (Specific, Measurable, Attainable, Relevant, Time-based). Identify gaps. Check technical feasibility against `kb/services/` and `kb/compatibility/`.
|
||||
|
||||
**Step 3 — Service Tiering:** After parsing databases, assign each workload a tier (Platinum/Gold/Silver/Bronze) based on SLA requirements, compliance needs, and business criticality. Use the auto-assignment rules in `kb/patterns/service-tiering.yaml`. Present the assignment and ask the architect to confirm or adjust.
|
||||
@@ -368,7 +333,7 @@ Capture enough about current state to architect the future. Frame the problem
|
||||
|
||||
1. **Select services** from `kb/services/` across the full OCI catalog
|
||||
2. **Dimension each service** using `kb/sizing/` rules. For Oracle DBs, use AWR metrics if available. Apply conversion ratios. For ADB-S, size base OCPUs for P75.
|
||||
3. **Compose topology** from `kb/patterns/` blocks. Check conflicts, add implied dependencies, apply compliance overlays. Use `kb/patterns/application-patterns.yaml` for workload-type guidance.
|
||||
3. **Compose topology** from `kb/patterns/` blocks. Check conflicts and apply compliance overlays. Use `kb/patterns/application-patterns.yaml` for workload-type guidance. **Do NOT silently add components** — only add technical dependencies from the closed whitelist in the Guardrails section below. Everything else must be proposed as optional in the pre-generation review.
|
||||
4. **Architecture Principles** — Select applicable principles from `kb/patterns/architecture-principles.yaml` based on the workload profile. Check `applies_when` conditions. Include in the deck as a governance slide.
|
||||
5. **Environment Catalogue** — Expand each workload into environments (Prod/Pre-Prod/Dev-Test/DR) using the tier templates in `kb/patterns/environment-catalogue.yaml`. Apply cost optimization rules. Include in the deck and in the cost estimate.
|
||||
6. **Design deployment** — environment strategy, IaC approach, CI/CD pipeline
|
||||
@@ -391,6 +356,28 @@ Capture enough about current state to architect the future. Frame the problem
|
||||
|
||||
#### Confirm (Solution Proposal)
|
||||
|
||||
**Completeness gate (MANDATORY before generating artifacts).** Before calling any generation tool (deck, diagram, BOM, PDF), verify that critical fields are populated based on engagement tier:
|
||||
|
||||
| Field | Small | Standard | Complex |
|
||||
|---|---|---|---|
|
||||
| customer_name | required | required | required |
|
||||
| workload_type | required | required | required |
|
||||
| databases (type + count) | required | required | required |
|
||||
| primary_region | required | required | required |
|
||||
| compliance_frameworks | — | required | required |
|
||||
| RTO / RPO | — | required | required |
|
||||
| team_size | — | required | required |
|
||||
| current_infrastructure | — | required | required |
|
||||
| migration_driver | — | required | required |
|
||||
| environment_strategy | — | — | required |
|
||||
| operational_model | — | — | required |
|
||||
| multi_region_topology | — | — | required |
|
||||
| data_residency | — | — | required |
|
||||
|
||||
- If **required** fields are missing: ask the user before generating.
|
||||
- If **optional** fields are missing: list them as assumptions in the output (e.g., "Assumed: PAYG pricing, single environment, no compliance requirements").
|
||||
- Fields tagged `source: inferred` in the workload profile count as populated but should be flagged as assumptions.
|
||||
|
||||
Assemble all design work into a proposal. Ensure all propositions are **SMART**. Quality matters — it must look professional.
|
||||
|
||||
**Outputs by tier:** See artifact matrix in [docs/engagement-tiers.md](docs/engagement-tiers.md)
|
||||
@@ -439,106 +426,23 @@ Every skill option that produces output MUST generate **readable, human-consumab
|
||||
|
||||
If a tool or agent generates YAML without the corresponding readable output, the task is **incomplete**. Always present the formatted result, then list the files saved.
|
||||
|
||||
### Output Directory Convention
|
||||
### Output directory, slide deck structure, format options, service categorization
|
||||
|
||||
All generated files MUST be saved inside a dedicated output folder per customer/initiative:
|
||||
|
||||
```
|
||||
examples/output-<customer>-<initiative>/
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `examples/output-meli-im06/` — MELI MySQL engagement
|
||||
- `examples/output-meli-im30/` — MELI ElasticSearch engagement
|
||||
- `examples/output-acme-migration/` — ACME cloud migration
|
||||
|
||||
This folder contains ALL outputs for that engagement: `.pptx`, `.drawio`, `.yaml` specs, `.pdf`, scorecards. The folder is gitignored via `examples/output-*/` — never commit customer data.
|
||||
|
||||
YAML spec files (architecture, workload-profile, diagram-spec) are saved IN the output folder, not loose in `examples/`. This keeps everything grouped and portable.
|
||||
|
||||
Default output is a **slide deck (.pptx)**. The architect can specify:
|
||||
|
||||
| Format | Output |
|
||||
|--------|--------|
|
||||
| `deck` (default) | 10-12 slide presentation |
|
||||
| `deck + drawio` | + editable architecture diagram |
|
||||
| `deck + doc` | + technical document (15-25 pages) |
|
||||
| `deck + xlsx` | + cost spreadsheet with formulas |
|
||||
| `deck + pdf` | + customer-facing PDF (branded, no internal refs) |
|
||||
| `pdf` | Customer PDF only |
|
||||
| `full` | Everything (pptx + drawio + docx + xlsx + pdf) |
|
||||
| `doc only` | Technical document without slides |
|
||||
| `deliver` | Handover + go-live checklist + success criteria |
|
||||
|
||||
### Slide Deck Structure
|
||||
|
||||
Slide count adapts to engagement tier (6-8 small, 10-12 standard, 12-16 complex):
|
||||
|
||||
1. **Title** — customer, project, date (dark background)
|
||||
2. **Value Story** — business driver, hypothesis, desired outcomes
|
||||
3. **Service Tiering** — workload-to-tier mapping (Platinum/Gold/Silver/Bronze) with SLA, RTO/RPO
|
||||
4. **Architecture Principles** — selected ECAL principles (Design/Deployment/Service) that govern the architecture
|
||||
5. **Architecture Diagram** — fills 85% of slide
|
||||
6. **Architecture Decisions** — 4-6 key decisions with rationale
|
||||
7. **HA/DR** — topology + RTO/RPO per tier
|
||||
8. **Security & Compliance** — controls grid, compliance badges
|
||||
9. **Environment Catalogue** — Prod/Pre-Prod/Dev-Test/DR per workload with sizing and isolation
|
||||
10. **Cost Estimate** — PAYG vs BYOL table with assumptions (all environments)
|
||||
11. **Cost Comparison** (optional) — vs current state or competitor
|
||||
12. **Migration Approach** — phased timeline, tools, downtime strategy
|
||||
13. **Operational RACI** — responsibility matrix (customer vs Oracle/partner)
|
||||
14. **Risk Register** — severity-coded risk table
|
||||
15. **Well-Architected Scorecard** — 5-pillar traffic-light indicators
|
||||
16. **Next Steps** — concrete SMART actions with dates
|
||||
|
||||
Use `tools/oci_deck_gen.py` for generation. Colors: teal `#2D5967`, copper `#AA643B`, purple `#804998`. Font: Segoe UI. Design standards: `config/output-formats.yaml`.
|
||||
|
||||
### Architecture Diagram
|
||||
|
||||
Use `tools/oci_diagram_gen.py` with OCI official styles from `kb/diagram/oci-toolkit-styles.yaml`. Containers, service blocks, connections, and typography rules are defined there.
|
||||
See [docs/skill/output-formats.md](docs/skill/output-formats.md) for the per-customer output folder convention, the complete format option matrix, the 16-slide deck structure, the diagram generation rules, and the service-to-color mapping.
|
||||
|
||||
---
|
||||
|
||||
## Service Categorization
|
||||
## Cookbook: Building Tool Payloads
|
||||
|
||||
| Category | Color | Use |
|
||||
|----------|-------|-----|
|
||||
| **Infrastructure** | Teal `#2D5967` | Compute, OKE, LB, Gateways, WAF, Bastion, Storage, Monitoring |
|
||||
| **Database** | Copper `#AA643B` | ADB-S/D, DBCS, ExaCS, MySQL, PostgreSQL, NoSQL, GoldenGate |
|
||||
| **Integration** | Purple `#804998` | DRG, Streaming, Queue, OIC, FastConnect, Service Connector Hub |
|
||||
| **Dormant** | Light gray `#DFDCD8` | Standby/inactive resources (DR tier) |
|
||||
| **Legacy** | Medium gray `#70665E` | Non-OCI systems (MQ Series, legacy middleware) |
|
||||
Before mapping customer requirements to SKUs for `generate_bom`, `generate_bom_appca`, or `generate_cost_estimate`, check [docs/bom-cookbook.md](docs/bom-cookbook.md) — it has copy-paste recipes for common patterns (ExaCS X11M BYOL, ADB-Dedicated, ADB-S + Block + FastConnect) and explicitly names the gotchas that otherwise burn exploration turns (e.g. ADB-Dedicated shares infrastructure SKUs with ExaCS — there are no separate `adb_dedicated` SKUs in the catalog).
|
||||
|
||||
If a requirement does not match a recipe, `grep` [`kb/pricing/oci-sku-catalog.yaml`](kb/pricing/oci-sku-catalog.yaml) and consult `kb/services/` before inventing SKUs.
|
||||
|
||||
---
|
||||
|
||||
## Knowledge Base
|
||||
|
||||
```
|
||||
kb/
|
||||
├── architecture-center/ # Oracle Architecture Center reference catalog
|
||||
│ └── catalog.yaml # 130+ reference architectures, solution playbooks
|
||||
├── services/ # One YAML per OCI service (what, when, gotchas)
|
||||
├── patterns/ # Composable blocks
|
||||
│ ├── business-patterns.yaml # Business-level patterns (DEFINE)
|
||||
│ ├── application-patterns.yaml # Application architecture patterns (DESIGN)
|
||||
│ ├── service-tiering.yaml # Service tier definitions (Platinum/Gold/Silver/Bronze)
|
||||
│ ├── architecture-principles.yaml # ECAL architecture principles (Design/Deployment/Service)
|
||||
│ ├── operational-raci.yaml # RACI matrix templates (fully/co/self-managed)
|
||||
│ ├── environment-catalogue.yaml # Environment templates per tier
|
||||
│ ├── database-ha/ # Database HA patterns
|
||||
│ ├── database-dr/ # Database DR patterns
|
||||
│ ├── networking-*/ # Networking patterns
|
||||
│ ├── compute-scaling/ # Compute auto-scaling
|
||||
│ ├── security-baseline/ # Security controls
|
||||
│ └── compliance-pci/ # PCI-DSS compliance
|
||||
├── sizing/ # CPU conversion ratios, IOPS, scaling rules
|
||||
├── pricing/ # Simplified pricing for estimation
|
||||
├── competitive/ # AWS/Azure/GCP service mapping
|
||||
├── well-architected/ # 5-pillar validation checklists
|
||||
├── diagram/ # OCI Toolkit styles and reference layouts
|
||||
├── compatibility/ # Feature matrices (ADB, etc.)
|
||||
└── field-knowledge/ # Real-world gotchas and lessons learned
|
||||
```
|
||||
KB lives under `kb/`. See [kb/README.md](kb/README.md) for the directory map, frontmatter requirements, refresh tooling, and contributor guide.
|
||||
|
||||
---
|
||||
|
||||
@@ -568,27 +472,71 @@ kb/
|
||||
- Present trade-offs explicitly. Let the architect decide.
|
||||
- Produce the **minimum needed** for the engagement tier — don't pad.
|
||||
|
||||
### Minimal Output — Work Silently
|
||||
|
||||
**Do NOT narrate your internal process.** The architect does not need a play-by-play of what you are doing. Specifically:
|
||||
|
||||
- **Do NOT** announce each file you are about to read ("Let me check the service catalog...", "Reading the pricing file...").
|
||||
- **Do NOT** list the KB files, templates, or patterns you are consulting.
|
||||
- **Do NOT** describe intermediate reasoning steps ("First I'll parse your notes, then I'll...", "Now I'm matching services against the catalog...").
|
||||
- **Do NOT** echo back the user's input as a summary before starting work.
|
||||
- **Do NOT** show progress updates for sub-steps ("Step 1 done, moving to step 2...").
|
||||
|
||||
**What TO show:**
|
||||
- Clarifying questions (when input is ambiguous or incomplete).
|
||||
- The pre-generation review (component confirmation before generating artifacts).
|
||||
- The final deliverable (scorecard, deck summary, file list, next-step menu).
|
||||
- Errors or blockers that require the architect's input.
|
||||
|
||||
**In short:** Go from input → clarifying question (if needed) → pre-generation confirmation → final output. Skip everything in between. The architect cares about results, not process.
|
||||
|
||||
---
|
||||
|
||||
## Guardrails
|
||||
|
||||
- **Only what the user asked for.** Never add services, components, or features the user did not request — this includes observability (Monitoring, Logging, Events), security services (Data Safe, Vault, Cloud Guard, WAF), sizing details, connection types (RPC, peering), and any "nice to have" additions. Adding unrequested components wastes the architect's time and erodes trust.
|
||||
- **Only what the user asked for.** Never add services, components, or features the user did not request — this includes observability (Monitoring, Logging, Events), security services (Data Safe, Vault, Cloud Guard, WAF), sizing details, connection types (RPC, peering), and any "nice to have" additions. Adding unrequested components wastes the architect's time and erodes trust. The ONLY exception is the closed whitelist of technical dependencies below.
|
||||
|
||||
- **Technical dependency whitelist (closed — nothing else is auto-added):**
|
||||
|
||||
| If the user requests… | Auto-include | Reason |
|
||||
|---|---|---|
|
||||
| FastConnect | DRG | FastConnect terminates on DRG — cannot work without it |
|
||||
| VPN Connect | DRG | IPSec tunnels terminate on DRG |
|
||||
| ADB-S / ExaCS with backup to Object Storage | Service Gateway | Backup traffic requires SGW for Oracle Services Network |
|
||||
| Any service in a public subnet | Internet Gateway | Public subnet routing requires IGW |
|
||||
| Any private subnet service needing internet egress | NAT Gateway | Private-to-internet routing requires NAT |
|
||||
| Cross-region DR (Data Guard, FSDR) | Remote Peering Connection (RPC) | Cross-region VCN connectivity requires RPC on both DRGs |
|
||||
|
||||
Everything NOT in this table — including Monitoring, Logging, Events, Vault, Data Safe, WAF, Cloud Guard, Bastion, management subnets, compartment boundaries — requires explicit user approval via the pre-generation review.
|
||||
|
||||
- **Ask, don't guess.** When requirements are ambiguous or incomplete, ask a clarifying question instead of filling in assumptions. A 10-second question saves a 10-minute redo.
|
||||
- **Pre-generation review.** Before generating any diagram or architecture artifact, confirm the component list with the user. Present what you understood and suggest optional additions they can approve or reject:
|
||||
```
|
||||
I'll generate a diagram with:
|
||||
✅ [list of explicitly requested components]
|
||||
|
||||
Want me to also include any of these?
|
||||
• Observability subnet
|
||||
• Compartment boundaries
|
||||
• Security services (Data Safe, Vault)
|
||||
• Gateways (IGW, NAT, SGW)
|
||||
• [other relevant options based on context]
|
||||
|
||||
Or just generate with the above?
|
||||
- **MANDATORY pre-generation review.** Before generating ANY diagram, deck, or architecture artifact, you MUST confirm the component list with the user. Never skip this step. Present three clearly separated sections:
|
||||
```
|
||||
This takes 5 seconds to confirm and prevents rework.
|
||||
I'll generate with:
|
||||
|
||||
REQUESTED (from your input):
|
||||
✅ [only components explicitly mentioned by the user]
|
||||
|
||||
TECHNICAL DEPENDENCIES (auto-added per whitelist):
|
||||
⚙️ [only items from the whitelist table above, with reason]
|
||||
|
||||
OPTIONAL — want me to add any of these?
|
||||
○ Observability (Monitoring, Logging, Events)
|
||||
○ Security services (Vault, Data Safe, WAF, Cloud Guard)
|
||||
○ Management subnet
|
||||
○ Compartment boundaries
|
||||
○ Bastion / jump host
|
||||
○ [other relevant options based on context]
|
||||
|
||||
Generate with the above, or adjust?
|
||||
```
|
||||
Wait for the user's response before generating. If the user says "just generate" or equivalent, proceed with only REQUESTED + TECHNICAL DEPENDENCIES (no optionals).
|
||||
|
||||
- **Source attribution.** When the user provides documents, URLs, meeting notes, or external data:
|
||||
- Cite the source when extracting data: "From [document/source]: [extracted fact]"
|
||||
- Clearly separate facts from the source vs. your own inferences
|
||||
- If the source contradicts the internal KB, flag the conflict explicitly and let the architect decide
|
||||
|
||||
## What You Do NOT Do
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
# Navigate to the project root
|
||||
cd oci-deal-accelerator
|
||||
|
||||
# Run Codex — it auto-discovers AGENTS.md and .agents/skills/
|
||||
# One-time: create virtual environment with all dependencies
|
||||
make venv
|
||||
|
||||
# Run Codex — it auto-discovers AGENTS.md, .agents/skills/, and .codex/config.toml
|
||||
codex
|
||||
|
||||
# Or explicitly load the skill
|
||||
@@ -18,6 +21,18 @@ codex --skill oci-deal-accelerator
|
||||
Codex automatically reads:
|
||||
- `AGENTS.md` at project root (project-level instructions)
|
||||
- `.agents/skills/oci-deal-accelerator/SKILL.md` (the skill definition)
|
||||
- `.codex/config.toml` (project sandbox + approval config — **enables network for pip**)
|
||||
|
||||
### Why `.codex/config.toml` matters
|
||||
|
||||
By default Codex CLI blocks network access and prompts before every command.
|
||||
The committed `.codex/config.toml` pre-configures this project with:
|
||||
|
||||
- `approval_policy = "never"` — no per-command prompts
|
||||
- `sandbox_mode = "workspace-write"` — agent can write in the repo
|
||||
- `network_access = true` — `pip install` and `make venv` actually work
|
||||
|
||||
Without this file, `make venv` fails with `No matching distribution found for pyyaml` because PyPI is unreachable from the sandbox.
|
||||
|
||||
### Option 2: Using Codex App
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ review_triggers:
|
||||
- event: "Oracle database version release"
|
||||
action: "Review all feature matrix entries. Mark untested. Validate within 14 days."
|
||||
- event: "Oracle pricing change"
|
||||
action: "Update kb/pricing/ files. Verify cost calculator accuracy."
|
||||
action: "Run python tools/refresh_sku_catalog.py --refresh and --refresh-domain compute. Both pull from the live Oracle pricing API."
|
||||
- event: "After customer engagement"
|
||||
action: "Run After-Engagement Review (AER). Add findings and KB updates."
|
||||
- event: "Quarterly"
|
||||
|
||||
@@ -20,15 +20,15 @@ domains:
|
||||
review_cadence: "quarterly"
|
||||
|
||||
- area: "kb/compatibility/"
|
||||
owner: { name: "TBD", team: "Database Specialists" }
|
||||
owner: { name: "Diego Cabrera", team: "Field SA" }
|
||||
review_cadence: "on Oracle version release + quarterly"
|
||||
|
||||
- area: "kb/pricing/"
|
||||
owner: { name: "TBD", team: "Solution Engineering" }
|
||||
review_cadence: "monthly (pricing changes frequently)"
|
||||
owner: { name: "Auto-refreshed", team: "Oracle Public Pricing API" }
|
||||
review_cadence: "automatic — refresh tools pull from the API on demand; freshness checker runs in welcome flow"
|
||||
|
||||
- area: "kb/competitive/"
|
||||
owner: { name: "TBD", team: "Competitive Intelligence" }
|
||||
owner: { name: "Diego Cabrera", team: "Field SA" }
|
||||
review_cadence: "quarterly + on competitor announcements"
|
||||
|
||||
- area: "kb/field-findings/"
|
||||
@@ -36,5 +36,5 @@ domains:
|
||||
review_cadence: "continuous"
|
||||
|
||||
- area: "kb/well-architected/"
|
||||
owner: { name: "TBD", team: "Cloud Architecture" }
|
||||
owner: { name: "Diego Cabrera", team: "Field SA" }
|
||||
review_cadence: "on Oracle WA Framework updates"
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
---
|
||||
taxonomy:
|
||||
products:
|
||||
- adb # generic ADB (covers both -s and -d)
|
||||
- adb-s
|
||||
- adb-d
|
||||
- dep
|
||||
@@ -26,6 +27,8 @@ taxonomy:
|
||||
- goldengate
|
||||
- data-safe
|
||||
- vault
|
||||
- rac
|
||||
- proxysql
|
||||
|
||||
versions:
|
||||
- 19c
|
||||
@@ -44,6 +47,42 @@ taxonomy:
|
||||
- sizing
|
||||
- compliance
|
||||
|
||||
features:
|
||||
- adg # Active Data Guard
|
||||
- ai-vector-search
|
||||
- vector-search
|
||||
- hnsw # Hierarchical Navigable Small World indexes
|
||||
- json
|
||||
- partitioning
|
||||
- refreshable-clone
|
||||
- elastic-pool
|
||||
- ecpu # ECPU billing model (vs OCPU)
|
||||
- connection-pooling
|
||||
- distributed
|
||||
- immutable
|
||||
- serialization
|
||||
|
||||
operations:
|
||||
- cli
|
||||
- maintenance-window
|
||||
- provisioning
|
||||
- planning
|
||||
- lead-time
|
||||
- capacity
|
||||
- node-split
|
||||
- zero-downtime
|
||||
- bidirectional
|
||||
- detection-delay
|
||||
- stale-reads
|
||||
|
||||
metrics:
|
||||
- latency
|
||||
- 100m # 100 million scale (e.g. vector counts)
|
||||
|
||||
limitations:
|
||||
- limitation
|
||||
- sr-required # Service Request required to enable / fix
|
||||
|
||||
severity_tags:
|
||||
- blocker
|
||||
- workaround-available
|
||||
|
||||
190
docs/bom-cookbook.md
Normal file
190
docs/bom-cookbook.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# BOM Cookbook — Building `generate_bom` Payloads
|
||||
|
||||
Copy-paste recipes that map common customer requirements to the exact OCI SKUs the
|
||||
`generate_bom`, `generate_bom_appca`, and `generate_cost_estimate` MCP tools expect.
|
||||
The goal is to skip the "grep the catalog and guess SKUs" exploration loop that
|
||||
burns tool calls on well-known patterns.
|
||||
|
||||
> **If the requirement does not match any recipe below, consult
|
||||
> [`kb/services/`](../kb/services/) and
|
||||
> [`kb/pricing/oci-sku-catalog.yaml`](../kb/pricing/oci-sku-catalog.yaml)
|
||||
> before inventing SKUs.** All SKUs below are verified against the catalog as of
|
||||
> 2026-04-20; re-`grep` the catalog if a recipe ever fails.
|
||||
|
||||
## Payload Shape
|
||||
|
||||
All three tools accept the same envelope:
|
||||
|
||||
```json
|
||||
{
|
||||
"customer_id": "acme-prod",
|
||||
"discount_pct": 0.35,
|
||||
"currency": "USD",
|
||||
"services": [
|
||||
{ "sku": "B90777", "quantity": 1 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `customer_id`: free-form identifier, used for output file naming.
|
||||
- `discount_pct`: decimal (0.35 = 35%). Applied to every line unless overridden.
|
||||
- `services[].quantity`: integer or float depending on the SKU metric (ECPUs, GB, hours).
|
||||
|
||||
---
|
||||
|
||||
## Recipe 1 — Exadata Cloud Service (ExaCS) X11M, BYOL
|
||||
|
||||
**When it matches:** "ExaCS X11M BYOL, N ECPUs, M TB storage, no DR" — customer-managed
|
||||
Oracle Database on dedicated Exadata hardware, BYOL licensing.
|
||||
|
||||
**SKUs:**
|
||||
|
||||
| SKU | Component | Typical qty |
|
||||
|-----|-----------|-------------|
|
||||
| `B90777` | Exadata Infrastructure — Base System | `1` per rack |
|
||||
| `B110627` | Exadata Database Server — X11M | `2` (Base/Quarter) — adjust per rack config |
|
||||
| `B110629` | Exadata Storage Server — X11M | `3` (Base/Quarter) — adjust per rack config |
|
||||
| `B110632` | Exadata Database ECPU — Dedicated Infra BYOL (X11M) | One per ECPU |
|
||||
|
||||
Swap `B110632` → `B110631` for PAYG (license-included) pricing.
|
||||
|
||||
**Payload (120 ECPUs, 120 TB, BYOL, standard Base System):**
|
||||
|
||||
```json
|
||||
{
|
||||
"customer_id": "acme-exacs",
|
||||
"discount_pct": 0.35,
|
||||
"currency": "USD",
|
||||
"services": [
|
||||
{ "sku": "B90777", "quantity": 1 },
|
||||
{ "sku": "B110627", "quantity": 2 },
|
||||
{ "sku": "B110629", "quantity": 3 },
|
||||
{ "sku": "B110632", "quantity": 120 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recipe 2 — Autonomous Database Dedicated (ADB-D), BYOL
|
||||
|
||||
**When it matches:** "ADB Dedicated, N ECPUs, M TB, BYOL" — Autonomous Database running
|
||||
on dedicated Exadata infrastructure.
|
||||
|
||||
**⚠️ Gotcha that burns tool calls:** ADB-Dedicated has **no separate infrastructure
|
||||
SKUs** in the catalog. It reuses the same Exadata dedicated infra SKUs as ExaCS
|
||||
(`B90777`, `B110627`, `B110629`) plus the same Exadata ECPU SKU (`B110631`/`B110632`).
|
||||
The Autonomous-vs-customer-managed distinction is a tenancy-level configuration,
|
||||
not a billing line item. Do not search for `autonomous_dedicated` SKUs — they do
|
||||
not exist.
|
||||
|
||||
**SKUs:** identical to Recipe 1.
|
||||
|
||||
**Payload (64 ECPUs, BYOL):**
|
||||
|
||||
```json
|
||||
{
|
||||
"customer_id": "acme-adbd",
|
||||
"discount_pct": 0.35,
|
||||
"currency": "USD",
|
||||
"services": [
|
||||
{ "sku": "B90777", "quantity": 1 },
|
||||
{ "sku": "B110627", "quantity": 2 },
|
||||
{ "sku": "B110629", "quantity": 3 },
|
||||
{ "sku": "B110632", "quantity": 64 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recipe 3 — Autonomous Database Serverless (ADB-S) + Block Volume + FastConnect
|
||||
|
||||
**When it matches:** "ADB-S ATP, N ECPUs, M TB data + block storage for app tier +
|
||||
FastConnect to on-prem" — the typical "app on OCI Compute, DB on ADB-S" pattern.
|
||||
|
||||
**SKUs:**
|
||||
|
||||
| SKU | Component | Metric |
|
||||
|-----|-----------|--------|
|
||||
| `B95701` | ADB ECPU (ATP or ADW) — license-included | ECPU/hour |
|
||||
| `B95703` | ADB ECPU BYOL — use instead of B95701 if BYOL | ECPU/hour |
|
||||
| `B95706` | ADB ATP data storage | GB/month |
|
||||
| `B95754` | ADB ADW data storage — use instead of B95706 for warehouse | GB/month |
|
||||
| `B95754a` | ADB backup storage | GB/month |
|
||||
| `B91961` | Block Volume storage (app tier) | GB/month |
|
||||
| `B91962` | Block Volume performance (VPU) — optional, for higher IOPS tiers | VPU/GB/month |
|
||||
| `B88326` | FastConnect 10 Gbps port | port-hour |
|
||||
|
||||
Swap `B88326` → `B88325` (1 Gbps) or `B93126` (100 Gbps) as needed.
|
||||
|
||||
**Payload (16 ECPUs ATP license-included, 2 TB data + 1 TB backup, 500 GB block, 10 G FastConnect):**
|
||||
|
||||
```json
|
||||
{
|
||||
"customer_id": "acme-adbs",
|
||||
"discount_pct": 0.35,
|
||||
"currency": "USD",
|
||||
"services": [
|
||||
{ "sku": "B95701", "quantity": 16 },
|
||||
{ "sku": "B95706", "quantity": 2048 },
|
||||
{ "sku": "B95754a", "quantity": 1024 },
|
||||
{ "sku": "B91961", "quantity": 500 },
|
||||
{ "sku": "B88326", "quantity": 1 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recipe 4 — Big Data Service + Data Science + Data Flow (analytics stack)
|
||||
|
||||
**When it matches:** "HDFS-managed cluster for ETL", "notebooks + model deployment",
|
||||
"managed Spark pipelines" — typical OCI analytics/AI workload mix.
|
||||
|
||||
**SKUs:**
|
||||
|
||||
| SKU | Component | Metric |
|
||||
|-----|-----------|--------|
|
||||
| `B91128` | Big Data Service — Compute Standard (real) | OCPU/hour |
|
||||
| `B91129` | Big Data Service — Compute Dense I/O (real) | OCPU/hour |
|
||||
| `B91130` | Big Data Service — Compute HPC (real) | OCPU/hour |
|
||||
| `B93555` | Big Data Service — Core (real) | OCPU/hour |
|
||||
| `EST-DS-NOTEBOOK` | **[Estimate]** Data Science notebook session — priced as underlying VM.Standard OCPU | OCPU/hour |
|
||||
| `EST-DS-MODEL` | **[Estimate]** Data Science model-deployment endpoint — priced as underlying VM.Standard OCPU | OCPU/hour |
|
||||
| `EST-DF-SPARK` | **[Estimate]** Data Flow managed Spark runtime — priced as underlying VM.Standard OCPU | OCPU/hour |
|
||||
|
||||
OCI Data Science and OCI Data Flow have no dedicated SKUs in the Oracle public
|
||||
pricing API — both are billed via the underlying Compute shape + Block/Object
|
||||
Storage consumed. The `EST-*` entries are placeholder estimates (VM.Standard3.Flex
|
||||
OCPU rate) so BOMs can include them as line items with an explicit "estimate"
|
||||
flag; confirm the actual shape and hours with the customer before quoting.
|
||||
|
||||
**Payload (16 BDS Standard + 8 BDS Dense I/O + 4 notebook + 2 model + 8 Spark):**
|
||||
|
||||
```json
|
||||
{
|
||||
"customer_id": "acme-analytics",
|
||||
"discount_pct": 0.30,
|
||||
"currency": "USD",
|
||||
"services": [
|
||||
{ "sku": "B91128", "quantity": 16 },
|
||||
{ "sku": "B91129", "quantity": 8 },
|
||||
{ "sku": "EST-DS-NOTEBOOK", "quantity": 4 },
|
||||
{ "sku": "EST-DS-MODEL", "quantity": 2 },
|
||||
{ "sku": "EST-DF-SPARK", "quantity": 8 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Add `B91961` (Block Volume) and `B91628` (Object Storage Standard) when the
|
||||
customer needs dedicated storage beyond the compute default.
|
||||
|
||||
---
|
||||
|
||||
## When a recipe doesn't fit
|
||||
|
||||
1. Grep the catalog: `grep -n "<product keyword>" kb/pricing/oci-sku-catalog.yaml`
|
||||
2. Check service docs under `kb/services/` for deployment-specific guidance.
|
||||
3. Check `kb/field-knowledge/` for known sizing/pricing gotchas.
|
||||
4. If a SKU still cannot be located, surface the gap to the user rather than guessing — fabricated SKUs break the BOM silently.
|
||||
88
docs/skill/ecal-readiness-format.md
Normal file
88
docs/skill/ecal-readiness-format.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# ECAL Readiness Scorecard Format
|
||||
|
||||
This document defines how option 12 (ECAL Readiness Score) presents its results.
|
||||
Referenced from `SKILL.md` § Welcome Flow → Behavior Rules → option 12.
|
||||
|
||||
## Scoring model
|
||||
|
||||
Each artefact has a status: ✅ Complete | 🟡 Partial | ❌ Missing | ⬜ Not Applicable (future phase).
|
||||
|
||||
Phase scores are calculated as:
|
||||
- ✅ = 1.0 point, 🟡 = 0.5 point, ❌ = 0 points, ⬜ = excluded from denominator
|
||||
- Phase score = (sum of points / applicable artefacts) × 100%
|
||||
|
||||
Overall ECAL Readiness = weighted average:
|
||||
- DEFINE: 25% weight
|
||||
- DESIGN: 50% weight (largest phase, most artefacts)
|
||||
- DELIVER: 25% weight
|
||||
|
||||
## Readiness levels
|
||||
|
||||
- 🟢 80-100% — Ready to proceed to next phase
|
||||
- 🟡 60-79% — Gaps exist but manageable; proceed with caution
|
||||
- 🟠 40-59% — Significant gaps; address before proceeding
|
||||
- 🔴 0-39% — Major gaps; phase needs substantial work
|
||||
|
||||
## Output format
|
||||
|
||||
The ECAL readiness score MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML file saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
|
||||
|
||||
```
|
||||
══════════════════════════════════════════
|
||||
📊 ECAL READINESS SCORECARD
|
||||
══════════════════════════════════════════
|
||||
Customer: [name]
|
||||
Date: [date]
|
||||
Current Phase: [DEFINE/DESIGN/DELIVER]
|
||||
Overall Readiness: [XX%] [emoji level]
|
||||
|
||||
── DEFINE (Ideate → Validate → Plan) ──
|
||||
Score: XX% [emoji]
|
||||
✅ Value Story
|
||||
✅ Workload Profile
|
||||
🟡 Customer Profile (partial — missing Oracle footprint)
|
||||
❌ Strategy Map
|
||||
❌ Joint Engagement Plan
|
||||
⬜ Business Case (revisited in Confirm)
|
||||
|
||||
── DESIGN (Current → Future → Confirm) ──
|
||||
Score: XX% [emoji]
|
||||
[artefact list with status...]
|
||||
|
||||
── DELIVER (Adopt → Operate → Improve) ──
|
||||
Score: XX% [emoji]
|
||||
[artefact list with status...]
|
||||
|
||||
── TOP 5 GAPS ──
|
||||
1. ❌ [artefact] — [why it matters] — [recommended action]
|
||||
2. ...
|
||||
|
||||
── RECOMMENDED NEXT ACTIONS ──
|
||||
1. [specific action]
|
||||
2. [specific action]
|
||||
3. [specific action]
|
||||
|
||||
── ENGAGEMENT RACI CHECK ──
|
||||
Roles identified: [list]
|
||||
Roles missing: [list]
|
||||
══════════════════════════════════════════
|
||||
```
|
||||
|
||||
## Files generated
|
||||
|
||||
Always list the files saved at the end of the scorecard:
|
||||
|
||||
```
|
||||
📁 Files saved:
|
||||
- examples/<customer>-ecal-scorecard.yaml
|
||||
```
|
||||
|
||||
## After ECAL scorecard menu
|
||||
|
||||
```
|
||||
What do you want to do?
|
||||
→ [A] Fix the top gap now (I'll generate the missing artefact)
|
||||
→ [B] Generate all missing artefacts for current phase
|
||||
→ [C] Export scorecard as a slide (.pptx)
|
||||
→ [D] Re-score after updates
|
||||
```
|
||||
73
docs/skill/output-formats.md
Normal file
73
docs/skill/output-formats.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Output Formats and Conventions
|
||||
|
||||
Referenced from `SKILL.md` § Output Generation.
|
||||
|
||||
## Output directory convention
|
||||
|
||||
All generated files MUST be saved inside a dedicated output folder per customer/initiative:
|
||||
|
||||
```
|
||||
examples/output-<customer>-<initiative>/
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `examples/output-meli-im06/` — MELI MySQL engagement
|
||||
- `examples/output-meli-im30/` — MELI ElasticSearch engagement
|
||||
- `examples/output-acme-migration/` — ACME cloud migration
|
||||
|
||||
This folder contains ALL outputs for that engagement: `.pptx`, `.drawio`, `.yaml` specs, `.pdf`, scorecards. The folder is gitignored via `examples/output-*/` — never commit customer data.
|
||||
|
||||
YAML spec files (architecture, workload-profile, diagram-spec) are saved IN the output folder, not loose in `examples/`. This keeps everything grouped and portable.
|
||||
|
||||
## Format options
|
||||
|
||||
Default output is a **slide deck (.pptx)**. The architect can specify:
|
||||
|
||||
| Format | Output |
|
||||
|--------|--------|
|
||||
| `deck` (default) | 10-12 slide presentation |
|
||||
| `deck + drawio` | + editable architecture diagram |
|
||||
| `deck + doc` | + technical document (15-25 pages) |
|
||||
| `deck + xlsx` | + cost spreadsheet with formulas |
|
||||
| `deck + pdf` | + customer-facing PDF (branded, no internal refs) |
|
||||
| `pdf` | Customer PDF only |
|
||||
| `full` | Everything (pptx + drawio + docx + xlsx + pdf) |
|
||||
| `doc only` | Technical document without slides |
|
||||
| `deliver` | Handover + go-live checklist + success criteria |
|
||||
|
||||
## Slide deck structure
|
||||
|
||||
Slide count adapts to engagement tier (6-8 small, 10-12 standard, 12-16 complex):
|
||||
|
||||
1. **Title** — customer, project, date (dark background)
|
||||
2. **Value Story** — business driver, hypothesis, desired outcomes
|
||||
3. **Service Tiering** — workload-to-tier mapping (Platinum/Gold/Silver/Bronze) with SLA, RTO/RPO
|
||||
4. **Architecture Principles** — selected ECAL principles (Design/Deployment/Service) that govern the architecture
|
||||
5. **Architecture Diagram** — fills 85% of slide
|
||||
6. **Architecture Decisions** — 4-6 key decisions with rationale
|
||||
7. **HA/DR** — topology + RTO/RPO per tier
|
||||
8. **Security & Compliance** — controls grid, compliance badges
|
||||
9. **Environment Catalogue** — Prod/Pre-Prod/Dev-Test/DR per workload with sizing and isolation
|
||||
10. **Cost Estimate** — PAYG vs BYOL table with assumptions (all environments)
|
||||
11. **Cost Comparison** (optional) — vs current state or competitor
|
||||
12. **Migration Approach** — phased timeline, tools, downtime strategy
|
||||
13. **Operational RACI** — responsibility matrix (customer vs Oracle/partner)
|
||||
14. **Risk Register** — severity-coded risk table
|
||||
15. **Well-Architected Scorecard** — 5-pillar traffic-light indicators
|
||||
16. **Next Steps** — concrete SMART actions with dates
|
||||
|
||||
Use `tools/oci_deck_gen.py` for generation. Colors: teal `#2D5967`, copper `#AA643B`, purple `#804998`. Font: Segoe UI. Design standards: `config/output-formats.yaml`.
|
||||
|
||||
## Architecture diagram
|
||||
|
||||
Use `tools/oci_diagram_gen.py` with OCI official styles from `kb/diagram/oci-toolkit-styles.yaml`. Containers, service blocks, connections, and typography rules are defined there.
|
||||
|
||||
## Service categorization
|
||||
|
||||
| Category | Color | Use |
|
||||
|----------|-------|-----|
|
||||
| **Infrastructure** | Teal `#2D5967` | Compute, OKE, LB, Gateways, WAF, Bastion, Storage, Monitoring |
|
||||
| **Database** | Copper `#AA643B` | ADB-S/D, DBCS, ExaCS, MySQL, PostgreSQL, NoSQL, GoldenGate |
|
||||
| **Integration** | Purple `#804998` | DRG, Streaming, Queue, OIC, FastConnect, Service Connector Hub |
|
||||
| **Dormant** | Light gray `#DFDCD8` | Standby/inactive resources (DR tier) |
|
||||
| **Legacy** | Medium gray `#70665E` | Non-OCI systems (MQ Series, legacy middleware) |
|
||||
78
docs/skill/wa-review-format.md
Normal file
78
docs/skill/wa-review-format.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# WA Review Output Format
|
||||
|
||||
This document defines how option 5 (Well-Architected Review) presents its results.
|
||||
Referenced from `SKILL.md` § Welcome Flow → Behavior Rules → option 5.
|
||||
|
||||
The WA review MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML files saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
|
||||
|
||||
## Terminal scorecard banner
|
||||
|
||||
```
|
||||
══════════════════════════════════════════════════════
|
||||
✅ OCI WELL-ARCHITECTED REVIEW — [Customer Name]
|
||||
══════════════════════════════════════════════════════
|
||||
Overall: [STATUS] — X/Y checks passed
|
||||
HIGH: N │ MEDIUM: N │ LOW: N
|
||||
══════════════════════════════════════════════════════
|
||||
|
||||
[emoji] SECURITY & COMPLIANCE X/Y passed
|
||||
[emoji] RELIABILITY & RESILIENCE X/Y passed
|
||||
[emoji] PERFORMANCE & COST X/Y passed
|
||||
[emoji] OPERATIONAL EFFICIENCY X/Y passed
|
||||
[emoji] DISTRIBUTED CLOUD X/Y passed | N/A
|
||||
```
|
||||
|
||||
Pillar emoji: 🟢 all passed, 🟡 medium gaps only, 🔴 any HIGH gap, ⬜ N/A
|
||||
|
||||
## HIGH severity gaps table
|
||||
|
||||
Present all HIGH gaps grouped by pillar in a markdown table:
|
||||
|
||||
```
|
||||
### HIGH severity gaps that must be addressed:
|
||||
|
||||
**[Pillar Name] (N HIGH)**
|
||||
| ID | Gap | Fix |
|
||||
|---|---|---|
|
||||
| CHECK-ID | Finding description | Recommended action |
|
||||
```
|
||||
|
||||
## MEDIUM and LOW gaps
|
||||
|
||||
- **MEDIUM gaps:** List as a compact bullet list grouped by pillar (ID + one-line finding + fix). Skip the table format to keep it concise.
|
||||
- **LOW gaps:** Mention count only, list individual items only if ≤ 5.
|
||||
|
||||
## Analysis section
|
||||
|
||||
After the gap tables, add a "Why so many gaps?" paragraph if total gaps > 20, explaining the root cause (e.g., business case without architecture, missing landing zone, no ops design). This contextualizes the score for the SA.
|
||||
|
||||
## Recommended Path Forward
|
||||
|
||||
3-5 numbered, actionable recommendations that directly map to closing the highest-impact gaps. Reference skill options where applicable (e.g., "Generate the architecture — option 1 or 2").
|
||||
|
||||
## Files Generated
|
||||
|
||||
Always list the files saved at the end of the review:
|
||||
|
||||
```
|
||||
📁 Files saved:
|
||||
- examples/<customer>-wa-scorecard.yaml
|
||||
- examples/<customer>-wa-architecture.yaml
|
||||
- examples/<customer>-wa-workload-profile.yaml
|
||||
```
|
||||
|
||||
## After WA Review menu
|
||||
|
||||
```
|
||||
What do you want to do?
|
||||
→ [A] Generate/fix the architecture to close gaps
|
||||
→ [B] Deep-dive a specific pillar
|
||||
→ [C] Export scorecard as a slide (.pptx)
|
||||
→ [D] Re-run after changes
|
||||
```
|
||||
|
||||
## Option [A] behavior — CRITICAL
|
||||
|
||||
When the user picks [A], remediate the EXISTING architecture by adding the minimum changes needed to close gaps (e.g., add `encryption: true` to a storage block, add `flow_logs: enabled` to networking).
|
||||
|
||||
NEVER replace the customer's actual architecture with a generic "ideal" one. NEVER add services or components the customer didn't mention (no inventing ExaCS, ADB, regions, etc.). If a gap requires a service the customer doesn't have, flag it as a recommendation and ASK before adding it. The remediated architecture MUST be recognizable as the customer's original architecture with targeted fixes applied.
|
||||
26
evaluations/README.md
Normal file
26
evaluations/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Evaluations
|
||||
|
||||
Baseline evaluation scenarios for the OCI Deal Accelerator skill, following
|
||||
the format recommended in the [Anthropic Agent Skills best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#build-evaluations-first).
|
||||
|
||||
These are **manual evaluations** — there is no automated test runner yet.
|
||||
Use them as a regression checklist after non-trivial changes to `SKILL.md`,
|
||||
`CLAUDE.md`, or the welcome flow.
|
||||
|
||||
## How to run
|
||||
|
||||
1. Open a fresh Claude Code conversation in this repo.
|
||||
2. For each `*.json` file in this directory:
|
||||
- Read the `query` field — paste it as the user message (or simulate the trigger described in the file).
|
||||
- If `files` is non-empty, attach those files as context.
|
||||
- Observe the assistant's behavior.
|
||||
- Manually verify each item in `expected_behavior` is met.
|
||||
3. Note any failures — file an issue or update the skill accordingly.
|
||||
|
||||
## Scenarios
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `welcome-flow.json` | Greeting → exact 14-option menu (verbatim from SKILL.md) |
|
||||
| `full-proposal.json` | Discovery notes → bypass menu, run full proposal flow |
|
||||
| `wa-review.json` | WA review request → scorecard format + saved YAML files |
|
||||
18
evaluations/full-proposal.json
Normal file
18
evaluations/full-proposal.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"skills": ["oci-deal-accelerator"],
|
||||
"query": "Customer: ACME Bank, retail banking, 200 branches across LATAM. Driver: migrating core banking from on-prem Exadata to OCI for cost reduction and DR. Current: 4-node RAC on X8M, ~12 TB DB, 2000 TPS peak, RTO 4h / RPO 15min. Compliance: PCI-DSS, local data residency. Timeline: 6 months. Budget: tight, exploring BYOL. They are also evaluating AWS RDS Custom for Oracle.",
|
||||
"files": [],
|
||||
"expected_behavior": [
|
||||
"Detects this is discovery notes and skips the welcome menu (no 14-option list shown)",
|
||||
"Goes directly into the full proposal flow (option 1 behavior)",
|
||||
"Builds a workload profile reflecting ACME Bank's stated requirements (does NOT invent services they did not mention)",
|
||||
"Recommends an architecture that addresses RTO/RPO, PCI-DSS, data residency, and BYOL — using kb/services/, kb/patterns/, and kb/well-architected/",
|
||||
"Cites at least one Oracle Architecture Center reference architecture from kb/architecture-center/catalog.yaml when there is a strong match",
|
||||
"Generates a slide deck (.pptx) as the primary deliverable, saved to examples/output-acme-bank-*/",
|
||||
"Includes a Cost Estimate slide that distinguishes BYOL vs PAYG using kb/pricing/",
|
||||
"Mentions the AWS RDS Custom for Oracle competitive context honestly using kb/competitive/aws-mapping.yaml",
|
||||
"Does NOT add observability/security services that ACME did not request, beyond what is required for stated compliance",
|
||||
"Asks clarifying questions when input is genuinely ambiguous, instead of inventing answers",
|
||||
"Surfaces relevant gotchas from kb/field-knowledge/ (e.g., Exadata-to-cloud migration risks)"
|
||||
]
|
||||
}
|
||||
20
evaluations/wa-review.json
Normal file
20
evaluations/wa-review.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"skills": ["oci-deal-accelerator"],
|
||||
"query": "5",
|
||||
"follow_up": "Single-region OCI architecture: ADB-S 8 ECPU in São Paulo, 2 VM.Standard.E5.Flex web tier behind a public load balancer, Object Storage for media. No backups configured, no FastConnect. Customer: SmallShop, e-commerce, no compliance requirements stated.",
|
||||
"files": [],
|
||||
"expected_behavior": [
|
||||
"After the user picks 5, asks for the architecture description (does not skip to scoring)",
|
||||
"Reads docs/skill/wa-review-format.md before producing the scorecard",
|
||||
"Parses the input into a workload profile YAML and architecture YAML",
|
||||
"Runs scripts/validate-architecture.py with both files",
|
||||
"Produces the formatted terminal scorecard with the exact banner format from docs/skill/wa-review-format.md (5 pillars, X/Y passed, HIGH/MEDIUM/LOW counts)",
|
||||
"Saves three YAML files under examples/: <customer>-wa-scorecard.yaml, <customer>-wa-architecture.yaml, <customer>-wa-workload-profile.yaml",
|
||||
"Lists the saved files at the end of the review",
|
||||
"Identifies the obvious gaps (no backups, no DR, no monitoring, single-AD) as HIGH severity",
|
||||
"Presents HIGH gaps as a markdown table grouped by pillar",
|
||||
"Presents MEDIUM gaps as compact bullets, not a table",
|
||||
"Offers the after-WA-review menu with options [A] [B] [C] [D]",
|
||||
"If the user picks [A], remediates the EXISTING architecture (adds encryption, backups, etc. to the actual services SmallShop has) — does NOT replace it with a generic 'ideal' architecture, does NOT invent services SmallShop did not mention"
|
||||
]
|
||||
}
|
||||
16
evaluations/welcome-flow.json
Normal file
16
evaluations/welcome-flow.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"skills": ["oci-deal-accelerator"],
|
||||
"query": "hola",
|
||||
"files": [],
|
||||
"expected_behavior": [
|
||||
"Reads SKILL.md before showing anything to the user (does not improvise the menu from memory or folder structure)",
|
||||
"Runs python tools/kb_freshness.py --check --json as a pre-flight step",
|
||||
"If freshness reports stale files with refreshable=true, prepends a banner asking the user [y/N] before proceeding",
|
||||
"If freshness reports stale files but none are refreshable, prepends a non-blocking informational banner without asking",
|
||||
"Shows the welcome banner exactly as defined in SKILL.md (no paraphrasing)",
|
||||
"Shows all 14 capability menu options in the correct 6 sections: DESIGN & PROPOSE (1-4), VALIDATE & CHECK (5-7), STRATEGY & BUSINESS (8), KNOWLEDGE BASE (9-11), ECAL GOVERNANCE (12), SA TOOLS (13-14)",
|
||||
"Does NOT invent options that are not in SKILL.md",
|
||||
"Does NOT omit options that are in SKILL.md",
|
||||
"If the freshness tool errors out, falls back to showing the welcome message silently — never blocks the user on tooling failures"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,378 @@
|
||||
[
|
||||
{
|
||||
"title": "Deploy Oracle Autonomous Database on Oracle Database@Azure",
|
||||
"url": "https://docs.oracle.com/en/solutions/deploy-autonomous-database-db-at-azure/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2024-10",
|
||||
"services": [
|
||||
"adb-s",
|
||||
"adg",
|
||||
"azure"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"azure",
|
||||
"ha-dr",
|
||||
"autonomous"
|
||||
],
|
||||
"summary": "Multi-AZ deployment of ADB-S on Database@Azure with Autonomous Data Guard. Recommends VNet peering between app and DB VNets, TAC for availability, and ADG standby in a different AZ for automatic failover.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Oracle MAA for Oracle Database@Azure",
|
||||
"url": "https://docs.oracle.com/en/solutions/oracle-maa-db-at-azure/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-05",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"vault",
|
||||
"azure"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"azure",
|
||||
"ha-dr",
|
||||
"autonomous"
|
||||
],
|
||||
"summary": "Cross-AZ Data Guard on ExaCS in Database@Azure. Active Data Guard recommended for cross-AZ replication (block repair, app continuity, read offload). Backups to Autonomous Recovery Service.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Implement disaster recovery with local and regional standbys on Oracle Database@Azure",
|
||||
"url": "https://docs.oracle.com/en/solutions/local-regional-standby-dr-db-at-azure/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-05",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"azure",
|
||||
"fsdr"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"azure",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Local standby for HA within same region, regional standby for DR across Azure regions. Uses Active Data Guard with Fast-Start Failover. Recommends Full Stack DR service for automated failover orchestration.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Implement disaster recovery with multi-region standby on Oracle Database@Azure",
|
||||
"url": "https://docs.oracle.com/en/solutions/multi-region-standby-dr-db-at-azure/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-04",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"azure"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"azure",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Multi-region DR for ExaCS on Database@Azure using Data Guard. Cross-region standby with switchover/failover capabilities. Includes network topology for Azure-to-Azure cross-region connectivity.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Implement cross-region disaster recovery for Exadata Database on Oracle Database@Azure",
|
||||
"url": "https://docs.oracle.com/en/solutions/exadb-dr-on-db-azure/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-01",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"azure",
|
||||
"fsdr"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"azure",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Cross-region DR for ExaCS on Database@Azure. OCI-managed networks for peering (better performance, first 10 TB/month free). Data Guard for cross-region replication, FSDR for automated failover orchestration.\n",
|
||||
"terraform": "https://github.com/oracle-quickstart/oci-multicloud-azure"
|
||||
},
|
||||
{
|
||||
"title": "Deploy Active Data Guard Far Sync to protect data across Oracle Database@Azure regions",
|
||||
"url": "https://docs.oracle.com/en/solutions/active-data-guard-far-sync-oracle-db-at-azure/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-02",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"azure"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"azure",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Far Sync instance for zero data loss protection across Azure regions. Synchronous redo transport to Far Sync, async to remote standby. Eliminates performance impact of synchronous shipping over long distances.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Implement Oracle Database Autonomous Recovery Service with Oracle Database@Azure",
|
||||
"url": "https://docs.oracle.com/en/solutions/implement-recovery-service-db-at-azure/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-01",
|
||||
"services": [
|
||||
"exacs",
|
||||
"azure"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"azure",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Autonomous Recovery Service for ExaCS backups on Database@Azure. Automated backup management with real-time protection and point-in-time recovery capabilities.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Deploy Oracle Autonomous Database on Oracle Database@Google Cloud",
|
||||
"url": "https://docs.oracle.com/en/solutions/deploy-adb-db-at-google-cloud/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-03",
|
||||
"services": [
|
||||
"adb-s",
|
||||
"adg",
|
||||
"google-cloud"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"ha-dr",
|
||||
"autonomous"
|
||||
],
|
||||
"summary": "ADB-S on Database@Google Cloud with cross-region ADG. Non-overlapping CIDR between VPC and VCN required. App tier should span 2+ AZs with Google Global Load Balancer for failover.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Deploy Active Data Guard Far Sync to protect data across Oracle Database@AWS regions",
|
||||
"url": "https://docs.oracle.com/en/solutions/dr-active-dg-farsync-db-at-aws/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-09",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"aws"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"aws",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Far Sync instance for zero data loss protection across AWS regions. Synchronous redo to local Far Sync, asynchronous to remote standby. Requires cross-region AWS networking for redo transport.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Implement disaster recovery with local and regional standbys on Oracle Database@AWS",
|
||||
"url": "https://docs.oracle.com/en/solutions/dr-local-regional-standby-db-at-aws/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-09",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"aws",
|
||||
"fsdr"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"aws",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Local standby for HA within same AWS region, regional standby for DR. Active Data Guard with Fast-Start Failover for automated failover. Full Stack DR service for cross-service failover orchestration.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Implement disaster recovery with cross-zonal Data Guard on Oracle Database@AWS",
|
||||
"url": "https://docs.oracle.com/en/solutions/cross-zone-dr-db-at-aws/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-08",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"aws"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"aws",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Cross-AZ Data Guard on Database@AWS for HA. Synchronous redo transport between AZs for zero data loss. Fast-Start Failover for automatic database switchover on failure.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Implement disaster recovery with cross-regional Data Guard on Oracle Database@AWS",
|
||||
"url": "https://docs.oracle.com/en/solutions/implement-dr-cross-region-dg-odb-aws/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-08",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"aws"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"multicloud",
|
||||
"aws",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Cross-region Data Guard on Database@AWS for DR. Asynchronous redo transport for cross-region replication. Planned switchover for maintenance, forced failover for disaster scenarios.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Migrate Oracle RAC Databases to OCI",
|
||||
"url": "https://docs.oracle.com/en/solutions/ensure-ha-migrate-vmware-workloads-to-oci/migrate-oracle-rac-databases1.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-01",
|
||||
"services": [
|
||||
"exacs",
|
||||
"exascale",
|
||||
"adb-d",
|
||||
"base-db"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"migration",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Compares 4 RAC migration targets: ExaCS Dedicated, Exascale, ADB-D, and 2-node RAC on Base DB. ExaCS recommended for full RAC feature parity. Exascale for 23ai-only without dedicated infra commitment.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Deploy ORDS with High Availability on OCI",
|
||||
"url": "https://docs.oracle.com/en/solutions/deploy-ords-ha-oci/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-06",
|
||||
"services": [
|
||||
"compute",
|
||||
"load-balancer",
|
||||
"adb-s",
|
||||
"bastion"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"application",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Multi-instance ORDS behind OCI Load Balancer for HA REST access to Oracle DB. Works with ADB-S, DBCS, or ExaCS. Recommends DB in private subnet, ORDS in public with granular NSG rules.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Configure Data Guard for Oracle Exadata Database Service on Dedicated Infrastructure",
|
||||
"url": "https://docs.oracle.com/en/solutions/dataguard-exadata-dedicated-infrastructure/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-07",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Data Guard configuration for ExaCS Dedicated. Active Data Guard for read offload and automatic failover. Cross-region standby for DR with Fast-Start Failover for automated switchover.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Back up from Exadata on Dedicated Infrastructure to Zero Data Loss Autonomous Recovery",
|
||||
"url": "https://docs.oracle.com/en/solutions/back-up-exadata-dedicated-zero-data-loss-recovery/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-07",
|
||||
"services": [
|
||||
"exacs"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Autonomous Recovery Service for ExaCS backups. Automated backup management with real-time redo protection. Validates backup recoverability automatically.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Configure a standby database for disaster recovery using Oracle Exadata Database Service on Cloud@Customer",
|
||||
"url": "https://docs.oracle.com/en/solutions/exadata-cloud-at-customer-standby/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-07",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg"
|
||||
],
|
||||
"tags": [
|
||||
"database",
|
||||
"ha-dr"
|
||||
],
|
||||
"summary": "Data Guard standby on ExaCS Cloud@Customer for hybrid DR. On-premises primary with cloud standby, or cloud primary with on-premises standby for data sovereignty requirements.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Learn about maximum availability architecture for PeopleSoft",
|
||||
"url": "https://docs.oracle.com/en/solutions/learn-about-maa-for-peoplesoft/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2024-08",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"load-balancer",
|
||||
"compute"
|
||||
],
|
||||
"tags": [
|
||||
"application",
|
||||
"ha-dr",
|
||||
"peoplesoft"
|
||||
],
|
||||
"summary": "MAA for PeopleSoft on OCI. Active Data Guard for database HA/DR, multi-instance PIA behind Load Balancer, Process Scheduler on multiple nodes for batch processing resilience.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Provision and deploy a maximum availability solution for PeopleSoft on Oracle Cloud",
|
||||
"url": "https://docs.oracle.com/en/solutions/deploy-maa-for-peoplesoft-on-oci/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2024-08",
|
||||
"services": [
|
||||
"exacs",
|
||||
"adg",
|
||||
"load-balancer",
|
||||
"compute"
|
||||
],
|
||||
"tags": [
|
||||
"application",
|
||||
"ha-dr",
|
||||
"peoplesoft"
|
||||
],
|
||||
"summary": "Step-by-step PeopleSoft MAA deployment on OCI. Terraform stacks for infrastructure provisioning, Data Guard configuration, and PeopleSoft application tier setup.\n",
|
||||
"terraform": null
|
||||
},
|
||||
{
|
||||
"title": "Run PeopleSoft ERP and Autonomous Database in an HA multicloud deployment",
|
||||
"url": "https://docs.oracle.com/en/solutions/bread-multicloud-on-oci/index.html",
|
||||
"type": "reference-architecture",
|
||||
"date": "2025-02",
|
||||
"services": [
|
||||
"adb-s",
|
||||
"compute",
|
||||
"load-balancer"
|
||||
],
|
||||
"tags": [
|
||||
"application",
|
||||
"ha-dr",
|
||||
"multicloud",
|
||||
"peoplesoft",
|
||||
"autonomous"
|
||||
],
|
||||
"summary": "PeopleSoft HA with ADB-S across cloud providers. Application tier on OCI compute with database on ADB-S. Multi-AZ deployment for high availability with automatic failover.\n",
|
||||
"terraform": null
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@@ -0,0 +1,195 @@
|
||||
<mxfile host="app.diagrams.net" agent="OCI Deal Accelerator" version="24.0.0" type="device">
|
||||
<diagram name="OCI Architecture" id="oci-arch">
|
||||
<mxGraphModel dx="1900" dy="1200" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1900" pageHeight="1200" background="#FFFFFF" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="139766084988960" value="" style="group;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;connectable=1;pointerEvents=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="30" y="250" width="50" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766136148656" value="MELI
Applications" style="text;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;html=1;align=center;verticalAlign=top;fontFamily=Oracle Sans;fontSize=11;fontColor=#312D2A;" vertex="1" parent="139766084988960">
|
||||
<mxGeometry x="-10" y="48" width="70" height="20" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084989440" value="AWS
(Current State)" style="whiteSpace=wrap;rounded=1;fillColor=none;strokeColor=#70665E;dashed=1;html=1;strokeWidth=2;dashPattern=6 4;align=left;fontFamily=Oracle Sans;verticalAlign=top;fontColor=#70665E;fontSize=12;spacingLeft=5;spacingTop=5;arcSize=6;" vertex="1" parent="1">
|
||||
<mxGeometry x="10" y="80" width="220" height="180" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084990064" value="DynamoDB
30K Tables
70M RPM Peak" style="whiteSpace=wrap;rounded=1;fillColor=#FCFBFA;strokeColor=#2D5967;dashed=0;html=1;strokeWidth=1.5;fontColor=#2D5967;fontSize=11;fontFamily=Oracle Sans;arcSize=8;verticalAlign=middle;align=center;" vertex="1" parent="139766084989440">
|
||||
<mxGeometry x="30" y="60" width="160" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084989248" value="Oracle Cloud Infrastructure" style="whiteSpace=wrap;rounded=1;fillColor=none;strokeColor=#9E9892;dashed=1;html=1;strokeWidth=1;dashPattern=6 4;align=left;fontFamily=Oracle Sans;verticalAlign=top;fontColor=#312D2A;fontSize=13;fontStyle=1;spacingLeft=10;spacingTop=8;arcSize=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="80" width="1100" height="520" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084990976" value="Region — São Paulo" style="whiteSpace=wrap;rounded=1;fillColor=#F5F4F2;strokeColor=#9E9892;dashed=0;html=1;align=left;fontFamily=Oracle Sans;verticalAlign=top;arcSize=5;fontColor=#312D2A;fontSize=13;fontStyle=1;spacingLeft=10;spacingTop=8;" vertex="1" parent="139766084989248">
|
||||
<mxGeometry x="15" y="40" width="1070" height="460" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084991984" value="VCN KVS Production (10.0.0.0/16)" style="whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=#AE562C;dashed=1;html=1;strokeWidth=2;dashPattern=6 4;align=left;fontFamily=Oracle Sans;verticalAlign=top;fontColor=#AE562C;perimeterSpacing=0;fontSize=12;fontStyle=1;spacingLeft=8;spacingTop=6;" vertex="1" parent="139766084990976">
|
||||
<mxGeometry x="15" y="45" width="1040" height="400" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084992656" value="Application Subnet (Private) — 10.0.1.0/24" style="whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=#AE562C;dashed=1;html=1;strokeWidth=1;dashPattern=6 4;align=left;fontFamily=Oracle Sans;verticalAlign=top;fontColor=#AE562C;fontSize=11;fontStyle=1;spacingLeft=8;spacingTop=4;" vertex="1" parent="139766084991984">
|
||||
<mxGeometry x="8" y="32" width="1024" height="140" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069527424" value="" style="group;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;pointerEvents=1;connectable=1;" vertex="1" parent="139766084992656">
|
||||
<mxGeometry x="246" y="30" width="160" height="44" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766122318064" value="OCI NoSQL
Service Endpoint" style="text;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;html=1;overflow=visible;align=center;verticalAlign=top;fontFamily=Oracle Sans;fontSize=11;fontColor=#312D2A;spacingTop=2;" vertex="1" parent="139766084992656">
|
||||
<mxGeometry x="246" y="76" width="160" height="36" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069534000" value="" style="group;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;pointerEvents=1;connectable=1;" vertex="1" parent="139766084992656">
|
||||
<mxGeometry x="422" y="30" width="180" height="28" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766111346400" value="NoSQL
Elastic Pod Dedicated
(Isolated Compute)" style="text;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;html=1;overflow=visible;align=center;verticalAlign=top;fontFamily=Oracle Sans;fontSize=11;fontColor=#312D2A;spacingTop=2;" vertex="1" parent="139766084992656">
|
||||
<mxGeometry x="422" y="60" width="180" height="52" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069536112" value="" style="group;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;pointerEvents=1;connectable=1;" vertex="1" parent="139766084992656">
|
||||
<mxGeometry x="618" y="30" width="160" height="28" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766108726976" value="NoSQL Tables
30K Tables
70M RPM Peak" style="text;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;html=1;overflow=visible;align=center;verticalAlign=top;fontFamily=Oracle Sans;fontSize=11;fontColor=#312D2A;spacingTop=2;" vertex="1" parent="139766084992656">
|
||||
<mxGeometry x="618" y="60" width="160" height="52" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084986608" value="AI Memory Subnet (Private) — 10.0.3.0/24" style="whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=#AE562C;dashed=1;html=1;strokeWidth=1;dashPattern=6 4;align=left;fontFamily=Oracle Sans;verticalAlign=top;fontColor=#AE562C;fontSize=11;fontStyle=1;spacingLeft=8;spacingTop=4;" vertex="1" parent="139766084991984">
|
||||
<mxGeometry x="8" y="186" width="1024" height="140" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069531888" value="Oracle ADB-S 23ai
AI Vector Search
(Agent Memory)" style="whiteSpace=wrap;rounded=1;fillColor=#FCFBFA;strokeColor=#2D5967;dashed=0;html=1;strokeWidth=1.5;fontColor=#2D5967;fontSize=11;fontFamily=Oracle Sans;arcSize=8;verticalAlign=middle;align=center;" vertex="1" parent="139766084986608">
|
||||
<mxGeometry x="266" y="30" width="180" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069540912" value="OCI GenAI
Embedding
Service" style="whiteSpace=wrap;rounded=1;fillColor=#FCFBFA;strokeColor=#2D5967;dashed=0;html=1;strokeWidth=1.5;fontColor=#2D5967;fontSize=11;fontFamily=Oracle Sans;arcSize=8;verticalAlign=middle;align=center;" vertex="1" parent="139766084986608">
|
||||
<mxGeometry x="462" y="30" width="140" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069542640" value="" style="group;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;pointerEvents=1;connectable=1;" vertex="1" parent="139766084986608">
|
||||
<mxGeometry x="618" y="30" width="140" height="44" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069542784" value="OCI Functions
Memory Sync" style="text;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;html=1;overflow=visible;align=center;verticalAlign=top;fontFamily=Oracle Sans;fontSize=11;fontColor=#312D2A;spacingTop=2;" vertex="1" parent="139766084986608">
|
||||
<mxGeometry x="618" y="76" width="140" height="36" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084817968" value="Management Subnet (Private) — 10.0.2.0/24" style="whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=#AE562C;dashed=1;html=1;strokeWidth=1;dashPattern=6 4;align=left;fontFamily=Oracle Sans;verticalAlign=top;fontColor=#AE562C;fontSize=11;fontStyle=1;spacingLeft=8;spacingTop=4;" vertex="1" parent="139766084991984">
|
||||
<mxGeometry x="8" y="340" width="1024" height="120" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069584112" value="" style="group;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;pointerEvents=1;connectable=1;" vertex="1" parent="139766084817968">
|
||||
<mxGeometry x="384" y="30" width="120" height="34" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084991408" value="OCI
Monitoring" style="text;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;html=1;overflow=visible;align=center;verticalAlign=top;fontFamily=Oracle Sans;fontSize=11;fontColor=#312D2A;spacingTop=2;" vertex="1" parent="139766084817968">
|
||||
<mxGeometry x="384" y="66" width="120" height="36" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069586800" value="" style="group;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;pointerEvents=1;connectable=1;" vertex="1" parent="139766084817968">
|
||||
<mxGeometry x="520" y="30" width="120" height="34" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766132774896" value="OCI
Logging" style="text;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;html=1;overflow=visible;align=center;verticalAlign=top;fontFamily=Oracle Sans;fontSize=11;fontColor=#312D2A;spacingTop=2;" vertex="1" parent="139766084817968">
|
||||
<mxGeometry x="520" y="66" width="120" height="36" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069591360" value="" style="group;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;pointerEvents=1;connectable=1;" vertex="1" parent="139766084991984">
|
||||
<mxGeometry x="10" y="40" width="110" height="34" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069586224" value="Service
Gateway" style="text;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=none;dashed=0;html=1;overflow=visible;align=center;verticalAlign=top;fontFamily=Oracle Sans;fontSize=11;fontColor=#312D2A;spacingTop=2;" vertex="1" parent="139766084991984">
|
||||
<mxGeometry x="10" y="76" width="110" height="36" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084992224" style="elbow=vertical;endFill=0;startFill=0;labelBackgroundColor=#FFFFFF;labelBorderColor=none;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;rounded=1;jettySize=auto;startArrow=none;endArrow=open;strokeColor=#312D2A;strokeWidth=1;endSize=6;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="139766084988960" target="139766084990064" value="Current: SDK calls">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084992896" style="elbow=vertical;endFill=0;startFill=0;labelBackgroundColor=#FFFFFF;labelBorderColor=none;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;rounded=1;jettySize=auto;startArrow=none;endArrow=open;strokeColor=#312D2A;strokeWidth=1;endSize=6;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="139766084988960" target="139766069527424" value="Target: OCI NoSQL SDK">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766108632320" style="elbow=vertical;endFill=0;startFill=0;labelBackgroundColor=#FFFFFF;labelBorderColor=none;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;rounded=1;jettySize=auto;startArrow=none;endArrow=open;strokeColor=#312D2A;strokeWidth=1;endSize=6;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="139766069527424" target="139766069536112" value="R/W Operations">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069577392" style="elbow=vertical;endFill=0;startFill=0;labelBackgroundColor=#FFFFFF;labelBorderColor=none;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;rounded=1;jettySize=auto;startArrow=none;endArrow=open;strokeColor=#312D2A;strokeWidth=1;endSize=6;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="139766069591360" target="139766069527424" value="Private access">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069591456" style="elbow=vertical;endFill=0;startFill=0;labelBackgroundColor=#FFFFFF;labelBorderColor=none;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;rounded=1;jettySize=auto;startArrow=none;endArrow=open;strokeColor=#312D2A;strokeWidth=1;endSize=6;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="139766069534000" target="139766069536112" value="Dedicated
Infrastructure">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069532176" style="elbow=vertical;endFill=0;startFill=0;labelBackgroundColor=#FFFFFF;labelBorderColor=none;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;rounded=1;jettySize=auto;startArrow=none;endArrow=open;strokeColor=#312D2A;strokeWidth=1;endSize=6;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="139766069536112" target="139766069542640" value="Memory Sync
(hot → warm)">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069537168" style="elbow=vertical;endFill=0;startFill=0;labelBackgroundColor=#FFFFFF;labelBorderColor=none;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;rounded=1;jettySize=auto;startArrow=none;endArrow=open;strokeColor=#312D2A;strokeWidth=1;endSize=6;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="139766069542640" target="139766069531888" value="Vectorize &
Store">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766069532272" style="elbow=vertical;endFill=0;startFill=0;labelBackgroundColor=#FFFFFF;labelBorderColor=none;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;rounded=1;jettySize=auto;startArrow=none;endArrow=open;strokeColor=#312D2A;strokeWidth=1;endSize=6;fontFamily=Oracle Sans;fontSize=10;fontColor=#312D2A;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="139766069540912" target="139766069531888" value="Embeddings">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="139766084991024" value="MELI KVS — OCI NoSQL Architecture" style="text;whiteSpace=wrap;rounded=0;dashed=0;html=1;fontSize=18;fontColor=#312D2A;fontFamily=Oracle Sans;align=center;verticalAlign=middle;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="0" y="8" width="1380" height="35" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="1002" value="" style="ellipse;fillColor=none;strokeColor=#2D5967;strokeWidth=2;" vertex="1" parent="139766084988960"><mxGeometry x="14" y="0" width="22" height="22" as="geometry"/></mxCell>
|
||||
<mxCell id="1003" value="" style="shape=mxgraph.basic.arc;dx=0.5;fillColor=none;strokeColor=#2D5967;strokeWidth=2;rotation=180;" vertex="1" parent="139766084988960"><mxGeometry x="9" y="24" width="32" height="22" as="geometry"/></mxCell>
|
||||
<mxCell id="nosql_endpoint_i2" parent="139766069527424" style="vsdxID=4;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="28.65116279069762" width="25.92248062015499" x="67.03875968992253" y="7.755381177908675e-14" /></mxCell>
|
||||
<mxCell id="nosql_endpoint_i3" parent="nosql_endpoint_i2" style="vsdxID=5;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lZTRcoMgEEW/htcdYAHlOU3+I9OY6tRqxpg2/fviQHXBEds3WO56rrC7DA/3+nyrmOT3cejfq6/mMtYMX5iUTVdXQzO6FcMjw8O1H6q3oX90F7+/nSfltProP6cvPH2e5lOK5N9+K7jfn7z29TF4sfDHSkEpQoKIM/hT+gAH/isJEWvBYBDhShQipYHCUHbbdMQnSQhcBdrmvPLEpwKFidPYplPIcs+mEwn5HyyCVXksQqF3sQjaZLFLSoggGBODpQGrYziPwXM1ID3eQBYIXMfMpBTcw1sbA4krXIv++rdz0ZFrni9Rphq5fooMe++B12xSN5tsUn1ZdlzTcQ/QjI2mSc3SlCVkkkbQGpKWXbp6ozKSQREbzQ8Vt1im0bVpWz/M6Hk6vVzITz48/gA=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="27.968992248061962" width="25.24031007751933" x="0.3410852713178288" y="0.3410852713178288" /></mxCell>
|
||||
<mxCell id="nosql_endpoint_i4" parent="nosql_endpoint_i2" style="vsdxID=6;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lVbRcsIgEPyavDJwFwh5tu1/ODXWTK1xorb270tKYg5uAvEtnrvswS07FLi5HLbnpgB5ufbdZ/PT7q6HAl8KgPZ0aPr26r4KfC1ws+/65qPvbqed/33eDsjh66v7Hla4e56WQqqBBfLXV0Cg/S+8efz7rfcE5f+vQNiRoCKGvIOv1JVAM4LGkhGqHEHIQWNJlaLElPjAqUJ1xzHI5atQ3qEs5vW1kPCsvhbK5PW1gHqNfrj/Y3siw6IMX7Fa2OS0KGUquVbKsGFjWMOOaCBsmHoFY9SCPqIwZaRPVobJQSayC20SGQgXdh8eFyEsHG/cLbBm6dyAgYBbYLHZrLccRTNrW2TiOhIn/l8Wz10sQlHswk7alVB1KE6u/rJJ4kQJp5RPoFxiydTGSsWOVYbbIus9Kia6q3xT2ROVPKZUJMwGWa2RrZMXPpZ11sS0rHO4zcqmg4mNJJtLhDHFQi0wOiA6u6lbKYuc3ybMgrS2LBLnVWOZRx6R7jDGrIujGb8yjWYCCSOTaXQYOGQazZqIK/Mk4srO4XnhJ7dMriLw8YWOTlgiMEQufwKw+5jfTvv2ePRPL/p//NZyJf9Ow9c/);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="28.65116279069762" width="25.92248062015499" /></mxCell>
|
||||
<mxCell id="nosql_endpoint_i5" parent="nosql_endpoint_i2" style="vsdxID=7;fillColor=#2d5967;gradientColor=none;shape=stencil(lVPbDoIwDP2avTZbyxg8e/kPoyiLCGbg7e+FdMq2BBPfejntOe06Qau+3l0rgbIfXHeuHvYw1ILWAtG2deXsMFqCNoJWx85VJ9fd2gP7192EnKxLd586PLlOSTnVoHyxz96WofubY6ziZJGBRA/3IQ0lceSJHMkNoPIgHypBGQ8iX/ZhpQSxwEwIpoyZg6aeRo1iipg5kEfhgF/iaN7GtsFq4sWUEjD/JVEVoLJEooFkOaRB61ji9wWWdvMBLPDmGWQ65p1beo5CgcmTN5m1UXoKtDByvJ+fp/MHdDTm6zzapuHjDvPpNY8h/gm0eQM=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="1.0232558139534864" width="6.480620155038747" x="9.550387596899206" y="19.78294573643407" /></mxCell>
|
||||
<mxCell id="nosql_endpoint_i6" parent="nosql_endpoint_i2" style="vsdxID=8;fillColor=#2d5967;gradientColor=none;shape=stencil(lVPRkoIwDPyavmbahFL67Ol/OCdK5zhwKnr494Kp0nLizb2lyya7TRdBq1O1PZYC5anz7Vf543ZdJehDILqmKr3rhkrQWtBq3/ry4Ntzs+PzcTsyx+q7vYwTeu6TYwfKK5+sBDR3ZMPkz7NntmKCKkBloSVA1gAx0iMjpEHrQAqQkkGoJwb0Q5hSwoJunkGmU91pZNAoFJg8lY28zXSewr+uXLsm2s/Ej/e14LLIQGLqUoPVqc3cAKqZTVD2/XqejAVlQjB29i7T0McjDGaKVDmyR2kg6MV909X8EZ1/kYdiSuje1TUHPP4+T/QA8d9A6xs=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="1.0232558139534864" width="6.480620155038747" x="9.550387596899206" y="13.302325581395323" /></mxCell>
|
||||
<mxCell id="nosql_endpoint_i7" parent="nosql_endpoint_i2" style="vsdxID=9;fillColor=#2d5967;gradientColor=none;shape=stencil(lVhdd9sgDP01edUBhPl47rr/0bOma866pidNt/bfT54NCGEb5y3Bku9FV0jCB7x7f354Ox6Mer9ezr+Of0+P1+cDfjsYc3p9Pl5OV/p1wPsD3j2dL8efl/PH6+P0/+1htBx//T7/Gd/wOfnFCDGOXkZ9TSvagBv+r3yfHH58XCYP3brMSwhxclGfZlrxFpSbjeYlNVvg9HeY/38hf7yCaQaItsZUNaACpWs8RgobG9y5WVWDkn1wArhG1QjKd2ERjL8FFsGaHuzgdsBWqC+nV5YKzH5aCB7cNsvikXLDg0gENDNmoao6mZAMVlCdBxThUSIZeIqahhm2Rriy4zpCC4dFRFRyzcyYkoNIoGJjWrXXuXZzaAk7p+YqNkvwDWx5bLpxkg51FQq0F1s5ROKxeTC9ARxE8lmIWO/P6fLilAhUSrRMQNDiqJCVD1v4GPJrMv7Q4BsP3gh829Ql7cA7gd/bv0vPC7zKWAneghPoIeSwJXRmtO8YMIeZS+hUUU2VQrD1GlQUyUjxq9mSyC7UbI2GKOh6THtapMs9Zr4R9BZdw/JB5y0GwZYiGWq6ZNRXloz0jco6B6qrrENweOgo6wzEW5S1dq61+4W1tGXbE9ZS8ATZBWFtvEVV4uo3A7sgK/lY0bAWdCUr3RfWImxWjFZXq9M529AVY6rzG7pSNZqX9ulKm7Rmiyz1Cu1qtjRQ6Zos9XaFNVsa1Bq2EYLoH8Vqvcd7ESz+5lTMXBMtRrJUci2UanYv2hfzWAlvMxMPTbi4bqn0m5Kzpk2BVH0xn/a9qRU0iOmYp2wqpjFDscS2IrG9L2mK2cpv1FfusXRuG7K0mSDY0pkTBS5E8CK3xsoiisaCuLJk9bRtSuIObXmtXdeWl+11bbv9oBWX9Zl1bVnHWpdWdsKesk2r3SHu2MTlwW3FHecBwXdB3GbS6KnbvcPEUlYSYT4jJXVJNzlHsnGrqKuxJtzMcTXhHYPvzQ71aJ0vV6kTmM1CRgOzFrcr2wxqpKgR8g25tfJg1LHwYLY/LGBGyjNt0565XqljawiihnKrvVf9hUwYb2LynDOSZbwJQ2/z1HNU70JjROTHgUWEnuuTWh7dcZoLTQ1OJmrzFFCDCxJcp1ThtxlZZYiiOAQLk1F37665S/GY5tFI1oxRnhqc2eyVnbnonE8y6oWfaRJzfd+9hOfx1Pkc1dBcmRwIWSml3vKU1zWkUxLoR/la+HR6eZk+NvLn8usiLU1fJvH+Hw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="27.286821705426302" width="24.558139534883672" x="0.6821705426356576" y="0.6821705426356576" /></mxCell>
|
||||
<mxCell id="nosql_endpoint_i8" parent="nosql_endpoint_i2" style="vsdxID=10;fillColor=#2d5967;gradientColor=none;shape=stencil(lZbbUsMgEIafJrc7wMIC1x7ew9FqM9bWSevp7SUSCAuV6h0hu/l+9hQGvDpu7143gxLH03R43nyMD6ftgNeDUuN+u5nGU1gNeDPg1eNh2jxNh7f9Q3x+vZst59XL4X3+wmf0swasnr2U+Io7Uoif59tofv82RXsZXzsE5xcHyT3Ep4obXoGQi03a8mBxscLK7QuzjfQlezfuC6mr/aLEgzI9qd4AGi41+JCqxAownosNVtZzsc6Ak1zubGW7oVJgZcN3jvOtB+NavuN8S0ANXnfxFoGwwUtb4QU4W+EdEHE8OTD18S141+OTzlHMfGr4hCDq4yP4KvzBinzFlykjZ6ul9Ig7Jgi2vzugAuSdYAQI8x+CDnXfKeDWQTpQ3RAWwUnNRiCqCi4DvWzJ0KX6Ygpl0IvdEiqKI/FlbqpcQkWhJb5o+G0FByPTxxetkWcNKOT4ss1WvFQcf6aB52/p7gARZ/ma8+cxoxu+lhemXbCx9PdpFwJKXa05l1lrkFrNmrmzuFLBVZa/A0xfEbIH1pjPuoLT+E9gZXPaEtmskxhboxQkAoe/B6n0WLrYpcI768BjqqkaoT1jg9W4vySFJCj1H4eQHe5Qh7p0SWnXUJVjmQ9V1VInzdVvn2u9eEsIi/WG8TjudvGCUr6vbyRhK95m8OYb);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="14.32558139534881" width="4.775193798449603" x="5.457364341085261" y="9.550387596899206" /></mxCell>
|
||||
<mxCell id="nosql_endpoint_i9" parent="nosql_endpoint_i2" style="vsdxID=11;fillColor=#2d5967;gradientColor=none;shape=stencil(lZbddtMwDMefJrc6tuTP6zHeY4d1NIfS7mQdlLdHwXFsy8Wwu0SR/PtblhRP9PB2fHo9TKjersvl2+Hn/Hw9TvRpQpzPx8MyX/lposeJHl4uy+Hrcnk/P6f316fVc336fvmxrnBLcWjA2TUK1a9kUaD0H8Pn5P/lfUkBOn3XDnLAZlHp9YbpNQCFzQHzkrhZbpQtBjef3RJcjT3N50pm5b+pUODdSKYFFVqZuiySpUYI1EplJ7StVm3Axlbs6mWGSfLgXIfX1OJ5W973fGr5SOCx49shHx043/GDFfwIRuA1kGvxpMGTwCMoGuHJAsrtU4cnB0ELvsvVV/gOtNx+AD0oljoiWQyKom4DnAfr24AIMXyEYD3Ej/gHDWGYQVcOfTMFyppKBu2erpzBwCjfnaA4wMBq/bB+QnYo+LBPir1+3N4sOz7mo6nrV+K57sZ4BSSGDMd4sXtuMjQdPohRw+2bE1Lx/ZBf+uLvdB6cPdyJ4lUdeEvY/SnXlEjkVMaRSr/XQ5bJIV7MmLWjYqtTK9Wq5L1gN2HUcLryT0CUZ1l1w3gsMzDPWwMUW3btlbNE+cTuZqmO2PpXgx6kdVeWe5UH6v97GwdmsHivhsJoFPT+fEJhOMw5JIpusODEr4xPJIp6VN0srf/2JJzuqv339YAfyt3iZT6d0tWk/i7vImxK9xh6/A0=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="14.32558139534881" width="4.775193798449603" x="15.348837209302296" y="9.550387596899206" /></mxCell>
|
||||
<mxCell id="nosql_dedicated_i2" parent="139766069534000" style="vsdxID=4;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="18.23255813953485" width="16.49612403100772" x="81.75193798449615" y="4.935242567760066e-14" /></mxCell>
|
||||
<mxCell id="nosql_dedicated_i3" parent="nosql_dedicated_i2" style="vsdxID=5;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lZTRcoMgEEW/htcdYAHlOU3+I9OY6tRqxpg2/fviQHXBEds3WO56rrC7DA/3+nyrmOT3cejfq6/mMtYMX5iUTVdXQzO6FcMjw8O1H6q3oX90F7+/nSfltProP6cvPH2e5lOK5N9+K7jfn7z29TF4sfDHSkEpQoKIM/hT+gAH/isJEWvBYBDhShQipYHCUHbbdMQnSQhcBdrmvPLEpwKFidPYplPIcs+mEwn5HyyCVXksQqF3sQjaZLFLSoggGBODpQGrYziPwXM1ID3eQBYIXMfMpBTcw1sbA4krXIv++rdz0ZFrni9Rphq5fooMe++B12xSN5tsUn1ZdlzTcQ/QjI2mSc3SlCVkkkbQGpKWXbp6ozKSQREbzQ8Vt1im0bVpWz/M6Hk6vVzITz48/gA=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="17.798449612403065" width="16.062015503875937" x="0.21705426356589105" y="0.21705426356589105" /></mxCell>
|
||||
<mxCell id="nosql_dedicated_i4" parent="nosql_dedicated_i2" style="vsdxID=6;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lVbRcsIgEPyavDJwFwh5tu1/ODXWTK1xorb270tKYg5uAvEtnrvswS07FLi5HLbnpgB5ufbdZ/PT7q6HAl8KgPZ0aPr26r4KfC1ws+/65qPvbqed/33eDsjh66v7Hla4e56WQqqBBfLXV0Cg/S+8efz7rfcE5f+vQNiRoCKGvIOv1JVAM4LGkhGqHEHIQWNJlaLElPjAqUJ1xzHI5atQ3qEs5vW1kPCsvhbK5PW1gHqNfrj/Y3siw6IMX7Fa2OS0KGUquVbKsGFjWMOOaCBsmHoFY9SCPqIwZaRPVobJQSayC20SGQgXdh8eFyEsHG/cLbBm6dyAgYBbYLHZrLccRTNrW2TiOhIn/l8Wz10sQlHswk7alVB1KE6u/rJJ4kQJp5RPoFxiydTGSsWOVYbbIus9Kia6q3xT2ROVPKZUJMwGWa2RrZMXPpZ11sS0rHO4zcqmg4mNJJtLhDHFQi0wOiA6u6lbKYuc3ybMgrS2LBLnVWOZRx6R7jDGrIujGb8yjWYCCSOTaXQYOGQazZqIK/Mk4srO4XnhJ7dMriLw8YWOTlgiMEQufwKw+5jfTvv2ePRPL/p//NZyJf9Ow9c/);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="18.23255813953485" width="16.49612403100772" /></mxCell>
|
||||
<mxCell id="nosql_dedicated_i5" parent="nosql_dedicated_i2" style="vsdxID=7;fillColor=#2d5967;gradientColor=none;shape=stencil(lVPbDoIwDP2avTZbyxg8e/kPoyiLCGbg7e+FdMq2BBPfejntOe06Qau+3l0rgbIfXHeuHvYw1ILWAtG2deXsMFqCNoJWx85VJ9fd2gP7192EnKxLd586PLlOSTnVoHyxz96WofubY6ziZJGBRA/3IQ0lceSJHMkNoPIgHypBGQ8iX/ZhpQSxwEwIpoyZg6aeRo1iipg5kEfhgF/iaN7GtsFq4sWUEjD/JVEVoLJEooFkOaRB61ji9wWWdvMBLPDmGWQ65p1beo5CgcmTN5m1UXoKtDByvJ+fp/MHdDTm6zzapuHjDvPpNY8h/gm0eQM=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="0.6511627906976731" width="4.12403100775193" x="6.07751937984495" y="12.589147286821682" /></mxCell>
|
||||
<mxCell id="nosql_dedicated_i6" parent="nosql_dedicated_i2" style="vsdxID=8;fillColor=#2d5967;gradientColor=none;shape=stencil(lVPRkoIwDPyavmbahFL67Ol/OCdK5zhwKnr494Kp0nLizb2lyya7TRdBq1O1PZYC5anz7Vf543ZdJehDILqmKr3rhkrQWtBq3/ry4Ntzs+PzcTsyx+q7vYwTeu6TYwfKK5+sBDR3ZMPkz7NntmKCKkBloSVA1gAx0iMjpEHrQAqQkkGoJwb0Q5hSwoJunkGmU91pZNAoFJg8lY28zXSewr+uXLsm2s/Ej/e14LLIQGLqUoPVqc3cAKqZTVD2/XqejAVlQjB29i7T0McjDGaKVDmyR2kg6MV909X8EZ1/kYdiSuje1TUHPP4+T/QA8d9A6xs=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="0.6511627906976731" width="4.12403100775193" x="6.07751937984495" y="8.46511627906975" /></mxCell>
|
||||
<mxCell id="nosql_dedicated_i7" parent="nosql_dedicated_i2" style="vsdxID=9;fillColor=#2d5967;gradientColor=none;shape=stencil(lVhdd9sgDP01edUBhPl47rr/0bOma866pidNt/bfT54NCGEb5y3Bku9FV0jCB7x7f354Ox6Mer9ezr+Of0+P1+cDfjsYc3p9Pl5OV/p1wPsD3j2dL8efl/PH6+P0/+1htBx//T7/Gd/wOfnFCDGOXkZ9TSvagBv+r3yfHH58XCYP3brMSwhxclGfZlrxFpSbjeYlNVvg9HeY/38hf7yCaQaItsZUNaACpWs8RgobG9y5WVWDkn1wArhG1QjKd2ERjL8FFsGaHuzgdsBWqC+nV5YKzH5aCB7cNsvikXLDg0gENDNmoao6mZAMVlCdBxThUSIZeIqahhm2Rriy4zpCC4dFRFRyzcyYkoNIoGJjWrXXuXZzaAk7p+YqNkvwDWx5bLpxkg51FQq0F1s5ROKxeTC9ARxE8lmIWO/P6fLilAhUSrRMQNDiqJCVD1v4GPJrMv7Q4BsP3gh829Ql7cA7gd/bv0vPC7zKWAneghPoIeSwJXRmtO8YMIeZS+hUUU2VQrD1GlQUyUjxq9mSyC7UbI2GKOh6THtapMs9Zr4R9BZdw/JB5y0GwZYiGWq6ZNRXloz0jco6B6qrrENweOgo6wzEW5S1dq61+4W1tGXbE9ZS8ATZBWFtvEVV4uo3A7sgK/lY0bAWdCUr3RfWImxWjFZXq9M529AVY6rzG7pSNZqX9ulKm7Rmiyz1Cu1qtjRQ6Zos9XaFNVsa1Bq2EYLoH8Vqvcd7ESz+5lTMXBMtRrJUci2UanYv2hfzWAlvMxMPTbi4bqn0m5Kzpk2BVH0xn/a9qRU0iOmYp2wqpjFDscS2IrG9L2mK2cpv1FfusXRuG7K0mSDY0pkTBS5E8CK3xsoiisaCuLJk9bRtSuIObXmtXdeWl+11bbv9oBWX9Zl1bVnHWpdWdsKesk2r3SHu2MTlwW3FHecBwXdB3GbS6KnbvcPEUlYSYT4jJXVJNzlHsnGrqKuxJtzMcTXhHYPvzQ71aJ0vV6kTmM1CRgOzFrcr2wxqpKgR8g25tfJg1LHwYLY/LGBGyjNt0565XqljawiihnKrvVf9hUwYb2LynDOSZbwJQ2/z1HNU70JjROTHgUWEnuuTWh7dcZoLTQ1OJmrzFFCDCxJcp1ThtxlZZYiiOAQLk1F37665S/GY5tFI1oxRnhqc2eyVnbnonE8y6oWfaRJzfd+9hOfx1Pkc1dBcmRwIWSml3vKU1zWkUxLoR/la+HR6eZk+NvLn8usiLU1fJvH+Hw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="17.364341085271285" width="15.627906976744155" x="0.4341085271317821" y="0.4341085271317821" /></mxCell>
|
||||
<mxCell id="nosql_dedicated_i8" parent="nosql_dedicated_i2" style="vsdxID=10;fillColor=#2d5967;gradientColor=none;shape=stencil(lZbbUsMgEIafJrc7wMIC1x7ew9FqM9bWSevp7SUSCAuV6h0hu/l+9hQGvDpu7143gxLH03R43nyMD6ftgNeDUuN+u5nGU1gNeDPg1eNh2jxNh7f9Q3x+vZst59XL4X3+wmf0swasnr2U+Io7Uoif59tofv82RXsZXzsE5xcHyT3Ep4obXoGQi03a8mBxscLK7QuzjfQlezfuC6mr/aLEgzI9qd4AGi41+JCqxAownosNVtZzsc6Ak1zubGW7oVJgZcN3jvOtB+NavuN8S0ANXnfxFoGwwUtb4QU4W+EdEHE8OTD18S141+OTzlHMfGr4hCDq4yP4KvzBinzFlykjZ6ul9Ig7Jgi2vzugAuSdYAQI8x+CDnXfKeDWQTpQ3RAWwUnNRiCqCi4DvWzJ0KX6Ygpl0IvdEiqKI/FlbqpcQkWhJb5o+G0FByPTxxetkWcNKOT4ss1WvFQcf6aB52/p7gARZ/ma8+cxoxu+lhemXbCx9PdpFwJKXa05l1lrkFrNmrmzuFLBVZa/A0xfEbIH1pjPuoLT+E9gZXPaEtmskxhboxQkAoe/B6n0WLrYpcI768BjqqkaoT1jg9W4vySFJCj1H4eQHe5Qh7p0SWnXUJVjmQ9V1VInzdVvn2u9eEsIi/WG8TjudvGCUr6vbyRhK95m8OYb);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="9.116279069767424" width="3.038759689922475" x="3.472868217054257" y="6.07751937984495" /></mxCell>
|
||||
<mxCell id="nosql_dedicated_i9" parent="nosql_dedicated_i2" style="vsdxID=11;fillColor=#2d5967;gradientColor=none;shape=stencil(lZbddtMwDMefJrc6tuTP6zHeY4d1NIfS7mQdlLdHwXFsy8Wwu0SR/PtblhRP9PB2fHo9TKjersvl2+Hn/Hw9TvRpQpzPx8MyX/lposeJHl4uy+Hrcnk/P6f316fVc336fvmxrnBLcWjA2TUK1a9kUaD0H8Pn5P/lfUkBOn3XDnLAZlHp9YbpNQCFzQHzkrhZbpQtBjef3RJcjT3N50pm5b+pUODdSKYFFVqZuiySpUYI1EplJ7StVm3Axlbs6mWGSfLgXIfX1OJ5W973fGr5SOCx49shHx043/GDFfwIRuA1kGvxpMGTwCMoGuHJAsrtU4cnB0ELvsvVV/gOtNx+AD0oljoiWQyKom4DnAfr24AIMXyEYD3Ej/gHDWGYQVcOfTMFyppKBu2erpzBwCjfnaA4wMBq/bB+QnYo+LBPir1+3N4sOz7mo6nrV+K57sZ4BSSGDMd4sXtuMjQdPohRw+2bE1Lx/ZBf+uLvdB6cPdyJ4lUdeEvY/SnXlEjkVMaRSr/XQ5bJIV7MmLWjYqtTK9Wq5L1gN2HUcLryT0CUZ1l1w3gsMzDPWwMUW3btlbNE+cTuZqmO2PpXgx6kdVeWe5UH6v97GwdmsHivhsJoFPT+fEJhOMw5JIpusODEr4xPJIp6VN0srf/2JJzuqv339YAfyt3iZT6d0tWk/i7vImxK9xh6/A0=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="9.116279069767424" width="3.038759689922475" x="9.767441860465098" y="6.07751937984495" /></mxCell>
|
||||
<mxCell id="nosql_tables_i2" parent="139766069536112" style="vsdxID=4;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="18.23255813953485" width="16.49612403100772" x="71.75193798449615" y="4.935242567760066e-14" /></mxCell>
|
||||
<mxCell id="nosql_tables_i3" parent="nosql_tables_i2" style="vsdxID=5;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lZTRcoMgEEW/htcdYAHlOU3+I9OY6tRqxpg2/fviQHXBEds3WO56rrC7DA/3+nyrmOT3cejfq6/mMtYMX5iUTVdXQzO6FcMjw8O1H6q3oX90F7+/nSfltProP6cvPH2e5lOK5N9+K7jfn7z29TF4sfDHSkEpQoKIM/hT+gAH/isJEWvBYBDhShQipYHCUHbbdMQnSQhcBdrmvPLEpwKFidPYplPIcs+mEwn5HyyCVXksQqF3sQjaZLFLSoggGBODpQGrYziPwXM1ID3eQBYIXMfMpBTcw1sbA4krXIv++rdz0ZFrni9Rphq5fooMe++B12xSN5tsUn1ZdlzTcQ/QjI2mSc3SlCVkkkbQGpKWXbp6ozKSQREbzQ8Vt1im0bVpWz/M6Hk6vVzITz48/gA=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="17.798449612403065" width="16.062015503875937" x="0.21705426356589105" y="0.21705426356589105" /></mxCell>
|
||||
<mxCell id="nosql_tables_i4" parent="nosql_tables_i2" style="vsdxID=6;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lVbRcsIgEPyavDJwFwh5tu1/ODXWTK1xorb270tKYg5uAvEtnrvswS07FLi5HLbnpgB5ufbdZ/PT7q6HAl8KgPZ0aPr26r4KfC1ws+/65qPvbqed/33eDsjh66v7Hla4e56WQqqBBfLXV0Cg/S+8efz7rfcE5f+vQNiRoCKGvIOv1JVAM4LGkhGqHEHIQWNJlaLElPjAqUJ1xzHI5atQ3qEs5vW1kPCsvhbK5PW1gHqNfrj/Y3siw6IMX7Fa2OS0KGUquVbKsGFjWMOOaCBsmHoFY9SCPqIwZaRPVobJQSayC20SGQgXdh8eFyEsHG/cLbBm6dyAgYBbYLHZrLccRTNrW2TiOhIn/l8Wz10sQlHswk7alVB1KE6u/rJJ4kQJp5RPoFxiydTGSsWOVYbbIus9Kia6q3xT2ROVPKZUJMwGWa2RrZMXPpZ11sS0rHO4zcqmg4mNJJtLhDHFQi0wOiA6u6lbKYuc3ybMgrS2LBLnVWOZRx6R7jDGrIujGb8yjWYCCSOTaXQYOGQazZqIK/Mk4srO4XnhJ7dMriLw8YWOTlgiMEQufwKw+5jfTvv2ePRPL/p//NZyJf9Ow9c/);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="18.23255813953485" width="16.49612403100772" /></mxCell>
|
||||
<mxCell id="nosql_tables_i5" parent="nosql_tables_i2" style="vsdxID=7;fillColor=#2d5967;gradientColor=none;shape=stencil(lVPbDoIwDP2avTZbyxg8e/kPoyiLCGbg7e+FdMq2BBPfejntOe06Qau+3l0rgbIfXHeuHvYw1ILWAtG2deXsMFqCNoJWx85VJ9fd2gP7192EnKxLd586PLlOSTnVoHyxz96WofubY6ziZJGBRA/3IQ0lceSJHMkNoPIgHypBGQ8iX/ZhpQSxwEwIpoyZg6aeRo1iipg5kEfhgF/iaN7GtsFq4sWUEjD/JVEVoLJEooFkOaRB61ji9wWWdvMBLPDmGWQ65p1beo5CgcmTN5m1UXoKtDByvJ+fp/MHdDTm6zzapuHjDvPpNY8h/gm0eQM=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="0.6511627906976731" width="4.12403100775193" x="6.07751937984495" y="12.589147286821682" /></mxCell>
|
||||
<mxCell id="nosql_tables_i6" parent="nosql_tables_i2" style="vsdxID=8;fillColor=#2d5967;gradientColor=none;shape=stencil(lVPRkoIwDPyavmbahFL67Ol/OCdK5zhwKnr494Kp0nLizb2lyya7TRdBq1O1PZYC5anz7Vf543ZdJehDILqmKr3rhkrQWtBq3/ry4Ntzs+PzcTsyx+q7vYwTeu6TYwfKK5+sBDR3ZMPkz7NntmKCKkBloSVA1gAx0iMjpEHrQAqQkkGoJwb0Q5hSwoJunkGmU91pZNAoFJg8lY28zXSewr+uXLsm2s/Ej/e14LLIQGLqUoPVqc3cAKqZTVD2/XqejAVlQjB29i7T0McjDGaKVDmyR2kg6MV909X8EZ1/kYdiSuje1TUHPP4+T/QA8d9A6xs=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="0.6511627906976731" width="4.12403100775193" x="6.07751937984495" y="8.46511627906975" /></mxCell>
|
||||
<mxCell id="nosql_tables_i7" parent="nosql_tables_i2" style="vsdxID=9;fillColor=#2d5967;gradientColor=none;shape=stencil(lVhdd9sgDP01edUBhPl47rr/0bOma866pidNt/bfT54NCGEb5y3Bku9FV0jCB7x7f354Ox6Mer9ezr+Of0+P1+cDfjsYc3p9Pl5OV/p1wPsD3j2dL8efl/PH6+P0/+1htBx//T7/Gd/wOfnFCDGOXkZ9TSvagBv+r3yfHH58XCYP3brMSwhxclGfZlrxFpSbjeYlNVvg9HeY/38hf7yCaQaItsZUNaACpWs8RgobG9y5WVWDkn1wArhG1QjKd2ERjL8FFsGaHuzgdsBWqC+nV5YKzH5aCB7cNsvikXLDg0gENDNmoao6mZAMVlCdBxThUSIZeIqahhm2Rriy4zpCC4dFRFRyzcyYkoNIoGJjWrXXuXZzaAk7p+YqNkvwDWx5bLpxkg51FQq0F1s5ROKxeTC9ARxE8lmIWO/P6fLilAhUSrRMQNDiqJCVD1v4GPJrMv7Q4BsP3gh829Ql7cA7gd/bv0vPC7zKWAneghPoIeSwJXRmtO8YMIeZS+hUUU2VQrD1GlQUyUjxq9mSyC7UbI2GKOh6THtapMs9Zr4R9BZdw/JB5y0GwZYiGWq6ZNRXloz0jco6B6qrrENweOgo6wzEW5S1dq61+4W1tGXbE9ZS8ATZBWFtvEVV4uo3A7sgK/lY0bAWdCUr3RfWImxWjFZXq9M529AVY6rzG7pSNZqX9ulKm7Rmiyz1Cu1qtjRQ6Zos9XaFNVsa1Bq2EYLoH8Vqvcd7ESz+5lTMXBMtRrJUci2UanYv2hfzWAlvMxMPTbi4bqn0m5Kzpk2BVH0xn/a9qRU0iOmYp2wqpjFDscS2IrG9L2mK2cpv1FfusXRuG7K0mSDY0pkTBS5E8CK3xsoiisaCuLJk9bRtSuIObXmtXdeWl+11bbv9oBWX9Zl1bVnHWpdWdsKesk2r3SHu2MTlwW3FHecBwXdB3GbS6KnbvcPEUlYSYT4jJXVJNzlHsnGrqKuxJtzMcTXhHYPvzQ71aJ0vV6kTmM1CRgOzFrcr2wxqpKgR8g25tfJg1LHwYLY/LGBGyjNt0565XqljawiihnKrvVf9hUwYb2LynDOSZbwJQ2/z1HNU70JjROTHgUWEnuuTWh7dcZoLTQ1OJmrzFFCDCxJcp1ThtxlZZYiiOAQLk1F37665S/GY5tFI1oxRnhqc2eyVnbnonE8y6oWfaRJzfd+9hOfx1Pkc1dBcmRwIWSml3vKU1zWkUxLoR/la+HR6eZk+NvLn8usiLU1fJvH+Hw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="17.364341085271285" width="15.627906976744155" x="0.4341085271317821" y="0.4341085271317821" /></mxCell>
|
||||
<mxCell id="nosql_tables_i8" parent="nosql_tables_i2" style="vsdxID=10;fillColor=#2d5967;gradientColor=none;shape=stencil(lZbbUsMgEIafJrc7wMIC1x7ew9FqM9bWSevp7SUSCAuV6h0hu/l+9hQGvDpu7143gxLH03R43nyMD6ftgNeDUuN+u5nGU1gNeDPg1eNh2jxNh7f9Q3x+vZst59XL4X3+wmf0swasnr2U+Io7Uoif59tofv82RXsZXzsE5xcHyT3Ep4obXoGQi03a8mBxscLK7QuzjfQlezfuC6mr/aLEgzI9qd4AGi41+JCqxAownosNVtZzsc6Ak1zubGW7oVJgZcN3jvOtB+NavuN8S0ANXnfxFoGwwUtb4QU4W+EdEHE8OTD18S141+OTzlHMfGr4hCDq4yP4KvzBinzFlykjZ6ul9Ig7Jgi2vzugAuSdYAQI8x+CDnXfKeDWQTpQ3RAWwUnNRiCqCi4DvWzJ0KX6Ygpl0IvdEiqKI/FlbqpcQkWhJb5o+G0FByPTxxetkWcNKOT4ss1WvFQcf6aB52/p7gARZ/ma8+cxoxu+lhemXbCx9PdpFwJKXa05l1lrkFrNmrmzuFLBVZa/A0xfEbIH1pjPuoLT+E9gZXPaEtmskxhboxQkAoe/B6n0WLrYpcI768BjqqkaoT1jg9W4vySFJCj1H4eQHe5Qh7p0SWnXUJVjmQ9V1VInzdVvn2u9eEsIi/WG8TjudvGCUr6vbyRhK95m8OYb);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="9.116279069767424" width="3.038759689922475" x="3.472868217054257" y="6.07751937984495" /></mxCell>
|
||||
<mxCell id="nosql_tables_i9" parent="nosql_tables_i2" style="vsdxID=11;fillColor=#2d5967;gradientColor=none;shape=stencil(lZbddtMwDMefJrc6tuTP6zHeY4d1NIfS7mQdlLdHwXFsy8Wwu0SR/PtblhRP9PB2fHo9TKjersvl2+Hn/Hw9TvRpQpzPx8MyX/lposeJHl4uy+Hrcnk/P6f316fVc336fvmxrnBLcWjA2TUK1a9kUaD0H8Pn5P/lfUkBOn3XDnLAZlHp9YbpNQCFzQHzkrhZbpQtBjef3RJcjT3N50pm5b+pUODdSKYFFVqZuiySpUYI1EplJ7StVm3Axlbs6mWGSfLgXIfX1OJ5W973fGr5SOCx49shHx043/GDFfwIRuA1kGvxpMGTwCMoGuHJAsrtU4cnB0ELvsvVV/gOtNx+AD0oljoiWQyKom4DnAfr24AIMXyEYD3Ej/gHDWGYQVcOfTMFyppKBu2erpzBwCjfnaA4wMBq/bB+QnYo+LBPir1+3N4sOz7mo6nrV+K57sZ4BSSGDMd4sXtuMjQdPohRw+2bE1Lx/ZBf+uLvdB6cPdyJ4lUdeEvY/SnXlEjkVMaRSr/XQ5bJIV7MmLWjYqtTK9Wq5L1gN2HUcLryT0CUZ1l1w3gsMzDPWwMUW3btlbNE+cTuZqmO2PpXgx6kdVeWe5UH6v97GwdmsHivhsJoFPT+fEJhOMw5JIpusODEr4xPJIp6VN0srf/2JJzuqv339YAfyt3iZT6d0tWk/i7vImxK9xh6/A0=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="9.116279069767424" width="3.038759689922475" x="9.767441860465098" y="6.07751937984495" /></mxCell>
|
||||
<mxCell connectable="0" id="functions_i2" parent="139766069542640" style="group" value="" vertex="1"><mxGeometry as="geometry" height="44.0" width="33.908256880733944" y="9.178386898625882e-14" x="53.04587155963303" /></mxCell>
|
||||
<mxCell id="functions_i3" parent="functions_i2" style="vsdxID=37;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="33.908256880733944" width="33.908256880733944" /></mxCell>
|
||||
<mxCell id="functions_i4" parent="functions_i3" style="vsdxID=38;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="33.908256880733944" width="33.908256880733944" /></mxCell>
|
||||
<mxCell id="functions_i5" parent="functions_i4" style="vsdxID=39;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lZPRDoIwDEW/Zq9LWUHCs+J/EAVZRCATFP/eYYdsAzW+td2922mzMtxey6zNmYBrp5pzfpfHrmS4Y0LIusyV7HTEMGW4LRqVn1TT10fK22xUjtGluY03DOSLOEajScCDCknC482rsif9oVdkCEggeIjGEfgWGASVwChMmsQchVGgqzBpEvLQfrWStUUJDuKb+QMhuHgz8ERnteDyTnDWVBzcVTiNvnFnCN/o9Cyi2CUEFy8Ab3xWB+hLfOJVxFnuI3+AnA1L6kEsG/HJB1zOxkNfBf39Hf/V62D++4WsKlod+9zfFV2iPcP0CQ==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="33.10091743119266" width="33.10091743119266" x="0.4036697247706422" y="0.4036697247706422" /></mxCell>
|
||||
<mxCell id="functions_i6" parent="functions_i4" style="vsdxID=40;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lZXRdoIwDIafprc9aUMpvXb6Hp6JgzMmHsSNvf1gLbQNCHpX4h/88iehDHe34njNmYRb29Sf+U95aguGb0zK8lLkTdn2J4Z7hrtz3eQfTX2/nOzz9Tgoh9NX/T28obN5BjmqIUvCr41Ijtl/4GD17/fGJgiXoXhiXIYgKdBJJ9IcR5ELJVy6SIdzkQulPMHwz6vyEsIGCRN+JlZpgxRfgFEEN6jJV5ClhDfwCqlqEbgvR8S8VE95e5c0wdU8lTFu77cmtIprEdMGIs+v9GPYIGG5GZQ1SBCzHstZPXI2LDhzCZdnkIzB5sy+qt/aCXihxbBuWaZiyyD2C6hZdAghdmp9YSAi21wWYHTyREInb+J3EQHANro5Sh41R8U7TeQLGy2Ih56BQgXbPJWCVPPcenj9c9thDNcp/U5O3Ry5Um5EjErsXPjorLu5Nrr9wV8E57Kq7D0S/k4vjj5kLx3c/wE=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="33.908256880733944" width="33.908256880733944" /></mxCell>
|
||||
<mxCell id="functions_i7" parent="functions_i3" style="vsdxID=41;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="32.29357798165138" width="32.29357798165138" x="0.8073394495412844" y="0.8073394495412844" /></mxCell>
|
||||
<mxCell id="functions_i8" parent="functions_i7" style="vsdxID=42;fillColor=#2d5967;gradientColor=none;shape=stencil(lZXLcoMwDEW/xlvGWDzidZr8R6YhhSmFDCEt+ftCbbAkB+Lu/LgyR/IVFrC/ladrIZS89V37WfxU574U8CaUqpqy6Kp+HAk4CNhf2q746Np7czbz62lSTqOv9ns6YTBxOo3SeIpS8mFW5N/saMR11SBxEqlkXft+78zJsdmMI62tOsZyOSgyfdipsrtAd2H5drpOJgmWzra4JIXSO0qFsOcVKSkaqgNQyVO4scZ5RgCZnBPqXSRjSukYONRMueQBXAAOY6OETv+84B6kno9bIBVF1LnLm175AL774KX9XniVGTtzNVzJ38so88puneRSSr2UxihbqK20nCqsszw9hwWvuzCImkV5wmkpKlKE2QQFhPkEBdiVhEPyhoPFWesdB5uUfstxfcDlIwx01+z6EwqKFUF/rgCf/jtgHLj//aWqa/Nc4H3+PoxL5m2Bwy8=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="32.29357798165138" width="32.29357798165138" /></mxCell>
|
||||
<mxCell id="functions_i9" parent="functions_i7" style="vsdxID=43;fillColor=#2d5967;gradientColor=none;shape=stencil(pZLRDsIgDEW/hlcCNG68z/kfS8aEiLCwOfXvhTTGTSPqfOul57YNuQSqQTe9IoINY/AHdTbtqAlsiRDGaRXMGCsCNYGq80Htgz+5FnXfJDJVRz+lCRf0seQQ7IqKM9Q7RK1xM/TeXAVn0JVgdn0WXf4AByrKJV5QuXk/Wxa0hP8MEijPGF5P+tnw4aQvDLF4hKYz1mLm5v3nkMUnDCjUNw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="6.862385321100918" width="8.880733944954128" x="3.229357798165138" y="21.394495412844037" /></mxCell>
|
||||
<mxCell id="functions_i10" parent="functions_i7" style="vsdxID=44;fillColor=#2d5967;gradientColor=none;shape=stencil(pZLdDsIgDIWfhlsC1Bm8nvM9lowJEWFhmz9vL6QxbhpZnHc99DttQw6Bstd1p4hg/RD8SV1NM2gCeyKEcVoFM8SKQEWgbH1Qx+BH16Du6kSm6uwvacINfSw5BLuj4gz1AVFr3AR9NlfBGXQlmF2fRec/sKFSzOktlcX30buCcvmfQQLlGcPHRb/yCwct87F4BaY11mLepv33gMUnDCdUDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="6.862385321100918" width="25.027522935779817" x="3.229357798165138" y="3.229357798165138" /></mxCell>
|
||||
<mxCell id="functions_i11" parent="functions_i7" style="vsdxID=45;fillColor=#2d5967;gradientColor=none;shape=stencil(pZLLDoMgEEW/hi0BplRdW/sfJmIhpWKQvv6+kklT7cPWupsL5w7D5BLIO122igjWBe/26myqoAlsiBCm0cqb0FcECgJ57bzaeXdsKtRtGclYHdwpdrigjzMWPYJdUaPaImpNM0D/BO8vvEWzjEqxBJ+AZ3xtEh0vLBM0XY/gFCiXn3snlK8W8VzSBCZ28jLQbMOXiX4w9MUjYbWxFgM6vH9OZH+EaYbiBg==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="6.862385321100918" width="16.954128440366972" x="3.229357798165138" y="12.513761467889909" /></mxCell>
|
||||
<mxCell id="functions_i12" parent="functions_i7" style="vsdxID=46;fillColor=#2d5967;gradientColor=none;shape=stencil(nZBLCoAwDERPk31tjuDnHoLVBmsrtf5ub0sQRdzobiZ5ycAA5pOuRwVSTMG7Xq3UBA1YgJRktfIUogIsAfPWedV5N9uG/VgnMqnBLenDxneZEOlGip09u4pRQ/aG/gTPhFf0Gf8J/otGcdXRkjHc5n3/rC+OuHosDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="5.651376146788991" width="6.055045871559633" x="21.79816513761468" y="12.917431192660551" /></mxCell>
|
||||
<mxCell id="functions_i13" parent="functions_i7" style="vsdxID=47;fillColor=#2d5967;gradientColor=none;shape=stencil(nZBLCoAwDERPk31tjuDnHoLVBmsrtf5ub0sQRdzobiZ5ycAA5pOuRwVSTMG7Xq3UBA1YgJRktfIUogIsAfPWedV5N9uG/VgnMqnBLenDxneZEOlGip09u4pRQ/aG/gTPhFf0Gf8J/otGcdXRkjHc5n3/rC+OuHosDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="5.651376146788991" width="6.055045871559633" x="21.79816513761468" y="21.79816513761468" /></mxCell>
|
||||
<mxCell id="functions_i14" parent="functions_i7" style="vsdxID=48;fillColor=#2d5967;gradientColor=none;shape=stencil(nZBLCoAwDERPk31tjuDnHoLVBmsrtf5ub0sQRdzobiZ5ycAA5pOuRwVSTMG7Xq3UBA1YgJRktfIUogIsAfPWedV5N9uG/VgnMqnBLenDxneZEOlGip09u4pRQ/aG/gTPhFf0Gf8J/otGcdXRkjHc5n3/rC+OuHosDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="5.651376146788991" width="6.055045871559633" x="14.128440366972479" y="21.79816513761468" /></mxCell>
|
||||
<mxCell id="monitoring_i2" parent="139766069584112" style="vsdxID=76;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="26.2018348623853" width="26.2018348623853" x="46.89908256880736" /></mxCell>
|
||||
<mxCell id="monitoring_i3" parent="monitoring_i2" style="vsdxID=77;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="26.2018348623853" width="26.2018348623853" /></mxCell>
|
||||
<mxCell id="monitoring_i4" parent="monitoring_i3" style="vsdxID=78;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lZPRDoIwDEW/Zq9LWUHCs+J/EAVZRCATFP/eYYdsAzW+td2922mzMtxey6zNmYBrp5pzfpfHrmS4Y0LIusyV7HTEMGW4LRqVn1TT10fK22xUjtGluY03DOSLOEajScCDCknC482rsif9oVdkCEggeIjGEfgWGASVwChMmsQchVGgqzBpEvLQfrWStUUJDuKb+QMhuHgz8ERnteDyTnDWVBzcVTiNvnFnCN/o9Cyi2CUEFy8Ab3xWB+hLfOJVxFnuI3+AnA1L6kEsG/HJB1zOxkNfBf39Hf/V62D++4WsKlod+9zfFV2iPcP0CQ==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="25.577981651376124" width="25.577981651376124" x="0.3119266055045869" y="0.3119266055045869" /></mxCell>
|
||||
<mxCell id="monitoring_i5" parent="monitoring_i3" style="vsdxID=79;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lZXRdoIwDIafprc9aUMpvXb6Hp6JgzMmHsSNvf1gLbQNCHpX4h/88iehDHe34njNmYRb29Sf+U95aguGb0zK8lLkTdn2J4Z7hrtz3eQfTX2/nOzz9Tgoh9NX/T28obN5BjmqIUvCr41Ijtl/4GD17/fGJgiXoXhiXIYgKdBJJ9IcR5ELJVy6SIdzkQulPMHwz6vyEsIGCRN+JlZpgxRfgFEEN6jJV5ClhDfwCqlqEbgvR8S8VE95e5c0wdU8lTFu77cmtIprEdMGIs+v9GPYIGG5GZQ1SBCzHstZPXI2LDhzCZdnkIzB5sy+qt/aCXihxbBuWaZiyyD2C6hZdAghdmp9YSAi21wWYHTyREInb+J3EQHANro5Sh41R8U7TeQLGy2Ih56BQgXbPJWCVPPcenj9c9thDNcp/U5O3Ry5Um5EjErsXPjorLu5Nrr9wV8E57Kq7D0S/k4vjj5kLx3c/wE=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="26.2018348623853" width="26.2018348623853" /></mxCell>
|
||||
<mxCell id="monitoring_i6" parent="monitoring_i2" style="vsdxID=80;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="24.95412844036695" width="24.95412844036695" x="0.6238532110091738" y="0.6238532110091738" /></mxCell>
|
||||
<mxCell id="monitoring_i7" parent="monitoring_i6" style="vsdxID=81;fillColor=#2d5967;gradientColor=none;shape=stencil(pVjbctsgEP0ave5wvzyn6X9kGqfW1LUzitM6f19U2YIFaxHWmxDniMNe2BWdfPrYv7zvOsE+zsPp1+5v/3red/JbJ0R/3O+G/hyeOvncyae307D7OZw+j6/T+P1lRI5Pv09/xi9cJp7XoPnIEuxresP+j75P4EN/TMAKhFrG/vgcpi/zaZKD91c0T+HsItDw6zoU11mJZ+W8tl5WxpAsbyhdDIvyDqtKZN/eMIalJXaQGHJXHHfgNRJIwoUH7tbDlQau1sO1BmnWwy0HKdbDHQfdsNUQfZYUk/vOO2C3cOW5d3J33fw3e1jmABllEMEV8fdDsRDpb5+bRQos0du4b5wMlyhpzkuUEEt2pLIYp7wEi+NFOHL73kSbP0iQEgi8DSGJ8cpT+DArcYIoQeHDjo1HeCPIDRQW0qT+VoPW8dhhxbErafMXSZXji4A1RVbNlBizBkQWsyqL2QSx6tROCVdLkGbz/nFwLWkTp3C8O1F8URQ2WiwMtKuqnsWBIEQeyKMFqcgvCI6RmaJBqU34ZkHbCVmyODCyZYWSYBhJ0KEk2m2EZknbCdhKVoHjLSuUBGNpggVtthGCpCZFD+DbtlwxalmFKyuEbqnJzQXe0HWVA7Ob8BU9oZfkTRsuCZr0mQou8JvwteMltOZNLigJ1tDNY9H8NxNqyZ8XkQJf1rr8zyxSkno3F8S5A+hQtUsQ6xrpsq+yZHVRwLO+zRKxxYBjzyj6PAhNDz5v6C7vTlfrat0Ny7OD8sqdLmy2uIj2zXqw1HPL/w6VEFpxcoWHeIfw1h8O0xVEOp/fOYRX032FfP4H);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="24.95412844036695" width="24.95412844036695" /></mxCell>
|
||||
<mxCell id="monitoring_i8" parent="monitoring_i6" style="vsdxID=82;fillColor=#2d5967;gradientColor=none;shape=stencil(pZJNDoMgEIVPw5Yg01b31t7DRCykFAxqf25fyKRBDYtid2+G781kyCNQj7IdBOFsnJy9iafqJkngTDhXRgqnJq8INATq3jpxdXY2HdZDG8ig7vYRJrzQVzAWPJy9scbqgqhWZoHuBL8bkuh2fRa8F13/QMloBSs4dpKzoaD8+J8hdpKGU0XLQ44h+4YfDF7E0PRKa8zc8n0bMt/CgELzAQ==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.8073394495412822" width="2.8073394495412822" x="1.8715596330275215" y="1.8715596330275215" /></mxCell>
|
||||
<mxCell id="logging_i2" parent="139766069586800" style="vsdxID=16;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="26.129629629629623" width="27.074074074074066" x="46.462962962962955" /></mxCell>
|
||||
<mxCell id="logging_i3" parent="logging_i2" style="vsdxID=17;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="26.129629629629623" width="27.074074074074066" /></mxCell>
|
||||
<mxCell id="logging_i4" parent="logging_i3" style="vsdxID=18;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lZRBcoMwDEVPw1YjSxjkdZrcI9OQwpSGDCFtevtC7UwsIGTYyeJ/8/jYSnhzKffnIiG8dG3zWfxUh65M+C0hqk5l0VZdXyW8TXhzbNrio22up4Nfn/eDcqi+mu9hh5v3kQObDi7CX99xDpD/OztvqKtTbMiARBsEMFswENhMG1Iw7rkhBZFl/fu19d9gwiuAOTjM2II38i0MirB0BGiCgrUiLMWBeU6JCtECyhIhajyClDRdT+M0IGq4KBWFOwsnFqzOEJfoRIBzTYgazyGkmeYjMKIRYxHP56IxY0PYNAexS6gGR1GygzTXsA9NaNgM3EvUTCDP17COz8cYNXaY6aGjafb3sKPDy9MfymPVLC9bELPm2jECsTLcc5y/1qsHx2tDXzzm1LGqaz/m4ufjuda3/Ezk7R8=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="25.499999999999993" width="26.444444444444436" /></mxCell>
|
||||
<mxCell id="logging_i5" parent="logging_i3" style="vsdxID=19;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lVbbVuMwDPyavOrYkuPLM7D/wVnKNofSckLZLX+Pu3EUW20VeEvVmXg8uqWju/ft49umQ/N+HA8vm3/D03Hb0X2HOOy3m3E45qeOHjq6ez6Mmz/j4WP/NP1+ezwjz0+vh7/nN5wmXnTQxzMLzecUQSD3P/Brwv/+GCeCLQwPHgvDCoo5YQFFQFtAJUSQykEnugSVkAeT6sN3w74WWxHKyRH6oKlNAXrbqqXEV57l1qgS6j2fpekNc+ibgmMA6lV7K8ocSuC88LdKwnwHC1JvlVsSoKtyqQcKjdwVvAHfXi/lBOJtAgZwriU4iL1CIFmeyUAMtwk9JB0u/ab5fLZ7obDdCBhat3NOkFq7KxBxsq3mxkK4Xv1Sa0Vg9UmUcnUfFs/dSdIkEpDrVbw6I36KX5tB5vsJNrphQYwq07plpFVR9JBpjdLnk2mUrba66WTdeepE3bH+ucuJO+hmNhfM9bJD8KKnVgj9UlPc5kErbA/U4nMjKL5lfPCS4LQDcvcJRRHIq5OK2rqxRikyQnAk329JIeQbkPQ0aZvBcandIlxshsDNziXDnGWVGRCj6nIxVJhlUkXF74rAey+hJna2l6XW+xQlZp5dCeyq1LxDvJKJS6krQzUTnLC1GgPI/nCFtqNDWbZKga2MvPywfLA9D7vd9L1X/y8/8HJo+jikhy8=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="26.129629629629623" width="27.074074074074066" /></mxCell>
|
||||
<mxCell id="logging_i6" parent="logging_i2" style="vsdxID=20;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="24.555555555555546" width="25.814814814814806" x="0.3148148148148147" y="0.3148148148148147" /></mxCell>
|
||||
<mxCell id="logging_i7" parent="logging_i6" style="vsdxID=21;fillColor=#2d5967;gradientColor=none;shape=stencil(lZPdcoIwEIWfJrc7Sdb8XVt9D0exZErBidjq2xeaAMla2undcjiHfBt2GW6v9eFSMcmvfejeqk9/6muGL0xK39ZV8P1QMdwx3J67UL2G7tae4vPlMDrH6r37GL9wjzmHoNSYkvwRFStAi29lHwPHW4gJ8RxJkpVgdJTucnZxl1xJsghOJBcmlwSNyYXUlc5vfJsBa9gQXuqnvAqcI7gKOMFVoJDQapCEdogZAmsA1TosL0gF5+vW/CZ+tD/9Bg3GlH1NibmrWZiacgKcLptaPLgyACXo4s97XIO0IHQJuQE6KQqsIpggyZxkMzdxI9hfrvPvuf53YCiWNTr7polbmL+nazdIcWVx9wU=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="5.35185185185185" width="13.222222222222218" x="9.759259259259256" y="17.94444444444444" /></mxCell>
|
||||
<mxCell id="logging_i8" parent="logging_i6" style="vsdxID=22;fillColor=#2d5967;gradientColor=none;shape=stencil(lZXRcoMgEEW/xtcdWEDhOU3/I9OYxmkaM8a05u+LQ0BYIm3fcL3XOXtdoBKb63F3aStk13HoP9rvbj8eK/FSIXbnYzt0o11VYluJzaEf2vehv5337vmym5Xz6rP/mr8wOR83oHB2Ibu7itEgXeXVGU7dOTVgnRoa0KZg0NCI1FCD4OsGCYhl/dttcD1wJxBgPBKnFjahF9XmIcIgYvIhEpnoUTEKGr0OGxkI/SprMGT0C2roJ4P3pFFKlP0p6NKHJ6V6ShrFc8/gJ8yCvmf0njUWUfznsJHBVRBBiiJtA7VIaS2J1ARXg1EprkVRZAo4YyktKlClEQ9635wsJrvoPSlwnoFyAsrCxpuy2QykQfS3rUXlGSlolaKylJOljIveM5Iky/89jTHbepSOpBhlNmU8gdBnv76RvOQpov0kT0ezLGfAVNqVHUFZPF//fSD/ZrCL5fw/dKeTuz7i9/S+sCV314jtDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="23.29629629629629" width="23.29629629629629" /></mxCell>
|
||||
<mxCell id="logging_i9" parent="logging_i6" style="vsdxID=23;fillColor=#2d5967;gradientColor=none;shape=stencil(nZLdCsIwDIWfJrcjNuvA6znfY7DOFms7uvn39rYEcQ4sxbtzki+5yAlQO+t+UiBwXoI/q7sZFg10ACGM0yqYJSqgDqgdfVCn4K9uYD/1iUzq4m9pw4PnJKYRgU+2O2R/ZNYat2Lfzb/gDNrIUvJ7pcCqbkphqivc/4Y3dxCyGM1eIc9G8cllNNZyrOv+NsdY4h+g7gU=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.5185185185185177" width="0.9444444444444442" x="1.8888888888888884" y="2.203703703703703" /></mxCell>
|
||||
<mxCell id="logging_i10" parent="logging_i6" style="vsdxID=24;fillColor=#2d5967;gradientColor=none;shape=stencil(nZBLCoAwDERPk31tjuDnHoLVBmsrtf5ub0sQRdzobiZ5ycAA5pOuRwVSTMG7Xq3UBA1YgJRktfIUogIsAfPWedV5N9uG/VgnMqnBLenDxneZEOlGip09u4pRQ/aG/gTPhFf0Gf8J/otGcdXRkjHc5n3/rC+OuHosDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="0.3148148148148147" width="0.3148148148148147" x="4.092592592592592" y="4.092592592592592" /></mxCell>
|
||||
<mxCell id="logging_i11" parent="logging_i6" style="vsdxID=25;fillColor=#2d5967;gradientColor=none;shape=stencil(nZBLCoAwDERPk31tjuDnHoLVBmsrtf5ub0sQRdzobiZ5ycAA5pOuRwVSTMG7Xq3UBA1YgJRktfIUogIsAfPWedV5N9uG/VgnMqnBLenDxneZEOlGip09u4pRQ/aG/gTPhFf0Gf8J/otGcdXRkjHc5n3/rC+OuHosDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="0.3148148148148147" width="0.3148148148148147" x="4.092592592592592" y="2.8333333333333326" /></mxCell>
|
||||
<mxCell id="logging_i12" parent="logging_i6" style="vsdxID=26;fillColor=#2d5967;gradientColor=none;shape=stencil(lZLZDoIwEEW/pq+T0qELz4j/QUKRRqQEcPt7WxsjaNDyNsu5N5PJJZiPTdlrwug4Dfaor6aaGoI7wpjpGj2YyVUEC4J5bQd9GOy5q0Lfl5701clevMMt6FgKmHkVo/cwSSh99vuAt6ab4akCqRa4YODbNYFESGS8/2sZBQsOii9wd57K1gWZBL485oe7pCDTWPj7L8iBi3UBE6Aw1p3GgpiA3PKQDc/eGJS/uCvemaxN24ZIz/efGXajkH8sHg==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.5185185185185177" width="2.5185185185185177" x="5.666666666666665" y="1.8888888888888884" /></mxCell>
|
||||
<mxCell id="logging_i13" parent="logging_i6" style="vsdxID=27;fillColor=#2d5967;gradientColor=none;shape=stencil(jVbLcsMgDPwaXzWAeJhz2v5HpnEaT9Mk4yRt+ve1i7FBih83hNcsKy2CAjfXw/ZSFUpcb835s/qpd7dDgS+FUvXpUDX1rR0V+FrgZn9uqo/mfD/tQnzZdshu9HX+7lZ4hP+MAtP9pMRvmBD/0VvAvt+bAJbhI0asTMHioUKoFGjfI/opDfGfB4YZGdeIMYLQc6QavM9plQSnc2qR06IGV+a8Iqc1s0JFTmgNdHFKmOyqn3ElKEu0ttmVOW9pwds56jSJ/ZQ3YE1OP1Sij6UQObX24wYxx0wQW8eIx1V7mpLkOd1ZFJgss1azd0CclSaTSozkaVWQYlaVeYRL7psokVc69d+06kVjl4qqTk5LNBXRTKqcHN/M5j3jsT6tPut5X3A50lkQfk6LI4lstVmZS7EjfXQTP6WGyBkhU92BWafkNUTHqAVoUkJUrISLshU3Lu9NinDbwRgDtyKy21JJN0tMnSMBCSvTjElNpjWr4eRNXQJM85N+rGl/8mBIc+TeHUET1MazuyBdOObXsWvoyYl1jH5RueMd8knDoD0yKQ0SxNpql/Q+ElA60ii4aMtz7ohkZvC8Yyx1gXYwPiz29fEY3iXpd/oQaafCIwZf/wA=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.8333333333333326" width="2.203703703703703" x="8.814814814814811" y="1.8888888888888884" /></mxCell>
|
||||
<mxCell id="logging_i14" parent="logging_i6" style="vsdxID=28;fillColor=#2d5967;gradientColor=none;shape=stencil(lVPbEoIgEP0aXhnYVcHnLv/RpCaTqUN2+/tgKEpIx952l3OYc/ZCcHWud31JgJ0H3R3LmyqGmuCaAKi2LrUaTERwQ3BVdbo86O7SFi7vdxZpo1N3tT/cHY8zZjnAHi532dZBG9V+QQXQdCk2ZZTxERiRIk4TQCz/fLFiNIrHKhJJZb7053dvfgtOQ4cBfH/RrtE8JvCg+XeIugAhBCPIq5ILKuQ/o8iA2nSKkIVzlrO+BIt8Ca/IOzMlP4p3yW+ENycDa4JTzmc2MrKWZDQT04Q/tn0WaoLPQVWqadw9fr+HB2hK7nhx8wQ=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.5185185185185177" width="2.203703703703703" x="12.277777777777773" y="1.8888888888888884" /></mxCell>
|
||||
<mxCell id="logging_i15" parent="logging_i6" style="vsdxID=29;fillColor=#2d5967;gradientColor=none;shape=stencil(jZXbbsIwDIafprdWEud4zdh7oFFGNUZRgQ3efqmStnFY2kpcJOZ3P8ex4wo31+PuUleCXW9d+1X/NvvbscK3SojmfKy75uZXFW4r3Bzarv7s2vt5H/aXXa/sV9/tT/+FR/CzCtD0XoI9g0UI6Lf+9x4cPu5d8OBBYBRoHl0GE8hoeYhg0TiantHEogLDVlowLiowVRSwyMFkWEaZ3IHKmElgkcH98Sh18cACpKRgNMAkhTMKVg6EpmRGsT7z3M5hGWU6AcrNMp0GnEVyNpthCdZR5uAwpXjKXhEqODhNwaOolOHEpXzcVBVN1o4xz+An1Xq+YWNjjHwJkuKVAqUyvL94Q/G+0rmaLW0JfLnCJAdpKB8RMMv+P201qQp8pSHrrPTD5Y5Og4wsbYdyWH16g8ANxafdM3Ry8uqI1yvCV1Xp8k/NOXkAU4+88goBWwEOq6Vq9SbtaMCpKmvJqVVyOg130q8sbWdA6cXsOv8YLV9uOixKjycNd8V48YtpOB2a0ynMtvT/fJh5UxiEuP0D);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="1.5740740740740735" width="2.5185185185185177" x="15.740740740740735" y="1.8888888888888884" /></mxCell>
|
||||
<mxCell id="logging_i16" parent="logging_i6" style="vsdxID=30;fillColor=#2d5967;gradientColor=none;shape=stencil(lZPbkoMgDIafhttMICJw3cN7dFq7Mmu1Q+3p7VcnthXdddi7JH6B/49E0OpS7s6FUHhpQ/Nd3P2hLQWthVK+Lovg2y4StBG0Ojah+ArNtT5wft71ZB+dmlt/woP7JGLfo/DJOWdbRitfj1CjQKeyGgFlBGcIOvu7QZn0w5MVU6c4VqEdZPmCiliD0ZDbMb2/Bh6enF8wlIwF4h58qLf19zCGkpWAL4oG6jMBmkKJM57pnTTE7iyBWXSXm5k760C62J3F2JrLII+dOYx9vd7cryLHlyb9s3+84EW0Cz5LcvRVxTs2/j5dqq7EC0mbHw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.203703703703703" width="2.203703703703703" x="18.888888888888882" y="1.8888888888888884" /></mxCell>
|
||||
<mxCell id="logging_i17" parent="logging_i6" style="vsdxID=31;fillColor=#2d5967;gradientColor=none;shape=stencil(nVXbcsIgEP2avO7ALgR4tvY/nBprpladqK39+yYFwiUGtW/k5Cxn71S0OG1Xx6ZCdjp3h4/mu12ftxW9VIjtftt07bk/VbSsaLE5dM17d7js1/b7uBqYw+nz8DXccLV2NQOFgxWyH4do4PoPebUGb5fOWnBHUKClM/EQB6otdEULKU9x37IG7YSuZCGNwIVjOUgioCqJa+MJo7hQoCgVNxhcdJAgH9aoH7McRBpqUdI3NQhM9UkAM6k+ZyxVJz6JPnAcgOpO7MHCAzrEhFP/vDNRcXzmJSieqo/lmRFXWcnHQo3StQDUqTRLZUXvHKWyrKRJJtzI0xt9XvsWkkVN5CCyJrvXY7wPxGQ9BlJm/T0RjjhJcLMp3rX7aBI92fkon/QQGYhsBFGDVKmPccfQNMmUs2b0pQqTO9+LNxqiz/04qzRleZf4nWaMbXhuU9KPZ7WgX/uJeUJ/3BxBP9qtvkcYGJ7qx7n0cyJBFOsvKVR2fgvG4+a3cDS28/WXxmfpgU7VebJKZL/CblLDfvsHWec9k9LjKB8yeOBhfNqgP4R3eNPudvYZj//n73YP2Teflr8=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.5185185185185177" width="1.5740740740740735" x="1.8888888888888884" y="6.925925925925924" /></mxCell>
|
||||
<mxCell id="logging_i18" parent="logging_i6" style="vsdxID=32;fillColor=#2d5967;gradientColor=none;shape=stencil(nZBLCoAwDERPk31tjuDnHoLVBmsrtf5ub0sQRdzobiZ5ycAA5pOuRwVSTMG7Xq3UBA1YgJRktfIUogIsAfPWedV5N9uG/VgnMqnBLenDxneZEOlGip09u4pRQ/aG/gTPhFf0Gf8J/otGcdXRkjHc5n3/rC+OuHosDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="0.3148148148148147" width="0.3148148148148147" x="4.092592592592592" y="9.129629629629626" /></mxCell>
|
||||
<mxCell id="logging_i19" parent="logging_i6" style="vsdxID=33;fillColor=#2d5967;gradientColor=none;shape=stencil(nZBLCoAwDERPk31tjuDnHoLVBmsrtf5ub0sQRdzobiZ5ycAA5pOuRwVSTMG7Xq3UBA1YgJRktfIUogIsAfPWedV5N9uG/VgnMqnBLenDxneZEOlGip09u4pRQ/aG/gTPhFf0Gf8J/otGcdXRkjHc5n3/rC+OuHosDw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="0.3148148148148147" width="0.3148148148148147" x="4.092592592592592" y="7.870370370370368" /></mxCell>
|
||||
<mxCell id="logging_i20" parent="logging_i6" style="vsdxID=34;fillColor=#2d5967;gradientColor=none;shape=stencil(lZLdDoIwDIWfZrfNto6NXaO+BwlDFpERwL+3l7kQQSOOu9P260naHIJZX+WtIZz2Q+dO5maLoSK4I5zbpjKdHUZFcE8wK11njp27NEWo29yTXp3d1Tvcw55WkEi/xekjdOirOgS4ts0MVhQUxsIiBaUXMAqg+vcCl5BGu9NYEBkotoCFmq6IcGZ0xZsLQB2Pf39EIkix8m8EpuL9p2EULBNI5Za/bErKH3gU70CWtq5DnufzzwCPrRB+3D8B);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.5185185185185177" width="2.5185185185185177" x="5.666666666666665" y="6.925925925925924" /></mxCell>
|
||||
<mxCell id="logging_i21" parent="logging_i6" style="vsdxID=35;fillColor=#2d5967;gradientColor=none;shape=stencil(lZTRdsIgDIafprc5kEAK1869h2fWtWfOeqpu7u3XDmwbcPV4Bz8JH4GfFLQ61ZtjVaA6nbv2o/putue6oJcCsTnUVdec+1FB64JWu7ar3rv2ctiG+XEzRA6jz/Zr2OEa8tCA0kMWqp+g6BJU+ae8hoS3SxcydAhwU0ZUkMFRkK4YJBUj4tRoMBwjSEbEqXVgzRJWSWZpgbVkzg4WFa8AjcSimqKipJVaAs+vSOf7RhRhRi/7A1lJJ87o7AD9En+eEyW24GzC54zPCrx7yLcM+km8IfCSbvpbRUknAzqp3riMjh5w0W2WE68ZoATOJitde7Bawt2dhx+j/rO6k3CNgJLt7zw7EEr0zWAjeNFvnqe7lN4fje4kUT2sdBHIyddCMIm57zxvXuX8n9wKT3vJvjk813z6wdS6ds1+HzrffD1tdb0U2iStfwE=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="2.5185185185185177" width="1.2592592592592589" x="9.129629629629626" y="6.925925925925924" /></mxCell>
|
||||
<mxCell id="logging_i22" parent="logging_i6" style="vsdxID=36;fillColor=#2d5967;gradientColor=none;shape=stencil(lVRBcsIwDHxNrhpbsmX7TOk/mBJKppQwAVr6+zq140RpyZSbo2jt1a6kilbn/eZUV6jOl659qz+b7WVf0VOF2Bz3dddc4qmidUWrXdvVr117PW7T92nTZ/an9/ajv+GWcEEB+x6F6itF0IA2P5HnBDg0xwnAGbASYAx4mgJerl16QqcE9sAmQ3LIYrnlhjlLg+ecNYQUUAbeKAMtqOF5Ktfr+3zNrwI9guP7AM0QrADYAMbfB5AG4scUIT9oXBQhB4GkIsYORIsi8S1FM0UMoJGKoF3wz4JBwXZe3ZysQ/BekuWRRSbmRqsKVzBWUmUHM+/UgnEMrAVRbcHig7KiBmslVVJgtaQaNSAtueKk6hwiBlzoNPVQ04ShRUp1akEMjj0rxXAMblGMqSPjIAae+eZAoxQjDiLOxPAEykoxxgn+e4qUlCM2rg9LdIMDw5Lu1JXMLRhQbuZdEaLQnS61wc7lrfaPNRgP4xLdNYdD2sHT//OlG0NpYdP6Gw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="6.925925925925924" width="7.240740740740739" x="5.35185185185185" y="16.68518518518518" /></mxCell>
|
||||
<mxCell id="logging_i23" parent="logging_i6" style="vsdxID=37;fillColor=#2d5967;gradientColor=none;shape=stencil(lZHdDoIwDIWfZrdNbcmAa8T3IGG4RWRkgD9vL3MxMg1E707brydNj+Bi0FWvBOEwOntSV1OPWvBeEJlOK2fGWQkuBReNdero7NTVoe4rT3p1thfvcAt7OUjyS4T30MBndQhsa7oFixGYQpass1++nALJdV4yJDJayBFowx+Bs4jf4cbpr+GP5n88ZZudxfvzjWnbENxy/pnU3Aopc/kA);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="3.148148148148147" width="3.148148148148147" x="4.7222222222222205" y="21.4074074074074" /></mxCell>
|
||||
<mxCell id="logging_i24" parent="logging_i6" style="vsdxID=38;fillColor=#2d5967;gradientColor=none;shape=stencil(lZXLcsIwDEW/JluNLfm5pu1/MCWUTClhArT07+vUMX6VkO4c+Sonkq6dhlan3frYNshO56F/b7+6zXnX0FOD2B127dCd3aqh54ZW235o34b+ctj45+N6VI6rj/5zfMPV5wkLBscsZN8+whn7fX7x8tfL4PXcbysOQk4JPM9gV/QBTcDspJlCVoIQk4p8yCBwM6lCSIKlOfoNFdhKA+XwKJkCpAHVQzQ3oGbRSgCpHF6UTRKUyNks53Idu72UWxScVpNDAjNpyX3sw06jAlnMOZ1hKNnERpb9D/TUYvSnx/bd4T+WzB2MzpAqkyOCmK/NxpRgLAFMF7XZapzuy2xenGSVk26ie0ZioKnobHxvOEIMLC8am3zihNImqmhh8VZUg3VT1Cbnp6rgKxlV9/nj0Zo/RwSoi/INiILvbH4bEdYqqme/lC+r+ystDCtRdANXD+lV93NrL/CqW8S7etvt9/6qT/fLu92F/H+Bnn8A);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="16.05555555555555" width="16.999999999999993" x="8.814814814814811" y="3.462962962962962" /></mxCell>
|
||||
<mxCell id="logging_i25" parent="logging_i6" style="vsdxID=39;fillColor=#2d5967;gradientColor=none;shape=stencil(lVbbUuMwDP2avGpsKb49s/AfDBSaodsyoeyWv193bcey0qTtW6JIPjrSkeKOHr62z5+bDtXXcTx8bP4Or8dtR786xGG/3YzDMT519NjRw9th3LyPh+/9a3r/fD57np9+H/6cTzilOKOBzDkK1U+yaKX+vz8l95fvMfnr9Nk6MDYH6DZCnTAZXABH2SebggGVw06UTN6BL17VZM0aejwm9C16BFO6xZ8SKujWgnUtevXJBqPA4hp2jcgG6sG4Fpnnl02IgCiYW+h9i64JjF9Ddx7It/j9hHWqPAtWgVcttBGsV3tNBE5gik5HcsG1gCwrxk3fSddAr1tkXseWW0Hm/aDW49Yeiw5z3Uz0lGlhuQCXGV+VdjyZsIXnQ1M4GtBCYHX8Cks200LtGXs37O/ZAe3KIISeGvfYrUCrQoqCD2JpxB1hRGkJUHJzgF6wQ3CC3OS0tLMUeKEmfnAZHrbZcJ5kBnNM8XQjfedAidbGIoqldWFpUphkNMEzr2zqQ9kMS/AspoxXABTK4knWioSr7F2cCLdafQ9BsPcKUDSf9yibfOy02JwXpF29FvC5rPT8ZJxLFOdZZjDSoPyd/DEWVpSfFbYsUjb9tSK9KD/3urX7UZ1WLHGuK5wnWSoSOyJ+2Xz0l8Tf7pYblkV8qLeTt2G3S5cb/l3eZqIp3YTo8R8=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="4.7222222222222205" width="4.407407407407406" x="12.907407407407403" y="9.444444444444441" /></mxCell>
|
||||
<mxCell id="logging_i26" parent="logging_i6" style="vsdxID=40;fillColor=#2d5967;gradientColor=none;shape=stencil(lZRNcoMwDIVP463Glvwjr9P0HpmGFKYUMoS05PaFmpSoMzjJTjx/knlIQtHmVO6OhUJ96rv2o/iu9n2p6EUhVk1ZdFU/Roq2ijaHtiveu/bc7NPzcTeRU/TZfk0VhpTnImicslBfkkIO4q/wmvi6am54QghR8AaQ13kD3j6BUwRygrcMAdcTtCyu9TqKEZx5HHcBiAXuETjzKuwA3eP1mcFRDn87d6lTJh1HAnutv0hu7saAs+QhXMvOEgcws5OB5FX6Mgshgs20PTiwckzu9CUyUJDuIiBl/TnQLP2Zvy+++DPARvrzYI20xx44SoO5ThB4ORi5sXhyYe7zY7Bs56Gq67Tct+f/t3mU0p+Atj8=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="4.7222222222222205" width="3.462962962962962" x="17.94444444444444" y="9.444444444444441" /></mxCell>
|
||||
<mxCell id="logging_i27" parent="logging_i6" style="vsdxID=41;fillColor=#2d5967;gradientColor=none;shape=stencil(lZXbcoIwEIafhtudZDcHcm3b93AqVqZWHNTWvn2hISQbRsC7sPzJt8ekoM3lsD1XBYrLtW0+q596dz0U9FIg1qdD1dbXblXQa0GbfdNWH21zO+3893nbK/vVV/Pdn3D3+5QF029C8esNUoj/7zevfr+1Xi79b+3A4LBB8h3ijt5gEWTQDCanQbpBRd5USkA9qILJgDBz9BEV2MYCSU6PmsFAFvQiWpZg9RzaYDglsLOoCcE4ThYcKwmcehKroJQcixbKkqPzgB1kuRacqhHUHDRPshrPw4lXoeYGHC6Gu1hgJNCG09PWCQFq0CXnxyakSWMTlwzoY316Yg741MSyBXl0/FFkMUHj4GigrJJdr4psdKQErRZjG0WP5rYEaTN8cvDAMklcOHWSxlqrrLCL4TscBzXwuzZVyPmpKri0ih8n+tH4itgywSULMrs7SIHJ+KlqMrTr+V2yRdbYNvb6mH+wlIVPoAzHJ6KV85zsCNeKBNKcnXoY0hHvyZnYJ7Xnk7ViVrpFfJ/29fHon7f0f/6edSb/FtLrHw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="12.592592592592588" width="12.592592592592588" x="11.33333333333333" y="5.037037037037035" /></mxCell>
|
||||
<mxCell id="sgw_i2" parent="139766069591360" style="vsdxID=43;fillColor=none;gradientColor=none;strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="23.032258064516107" width="23.306451612903206" x="43.3467741935484" /></mxCell>
|
||||
<mxCell id="sgw_i3" parent="sgw_i2" style="vsdxID=44;fillColor=#FCFBFA;gradientColor=none;shape=stencil(jVjLchQxDPyavaosv2SfefwHBYFsERJqCRD+Hi0zlsc9GS+3jSK7ZVlSt+cU3vy4//D97uTdj+fL09e73+dPz/en8Pbk/fnx/u5yftZfp/DuFN58frrcfbk8/Xz8tPz9/cPV8/rr29Ov6w4vy7oUSeS6yrs/i6VWqvWf5f2y4OPPy7KCF4coVP26ZDWxc4vhxa8+TJxXn9VUC8XVKSyWkMi1jVZTTRRm2L5QqSN29eR5RPeBUhrRi5DwCM+VYhzhi29hH+CzkIsjfnEU64jPkQqP+FIoA7zvmV9NkilN0Zkkj+iSKAmgOypweomWEIN3u+RLoDjFr5QDwHuqAC9mMXRH4kd0ocwArvHwDFzIpxE8VwqM4AxHVydfRvBMFe49W1mt4A/nx02TZPKt6FaDUPGzYOGW1B8jTZQLRJrbphZpogh3pE5hmqbUM9DAExXEdlCe6gP1ES0Yg9ZlkyRFslOv/gGSuhskvQLZlkTIUyDBPHmbPzZJrAksWN92OgAPFDBPbLOlg3vAZooFsV0AbAcTdEyUb6le85QqybTtvBVPCzVtirrNPOI4xpoKQahMtYyhqs+60dHI6ZOsYYvNLZs4lCtgi83/Dp6g61KmfJwmttyv3ql14WGoUE3KbQUitZvpkUaKYYzUdY5pkYYbnKgTDmgpdQ7q4DY+G7h/BTxBOSVuO72aJ0dhHE5JCWlKYpsVbEvYY7AexnisWE/qAzNCfW5hOxmxYzFKNWwAVloE7nYAGxvpHMNCGQftW7gflUIj8LWwYdJw2NGmmnhaHLoNzprYWr6PGk8ZGrgH/dLPGYE33Qw56ugHxkahpswERekAs+yYwO79dSKoJrX+WMHFY38tPh+n/juOU3VZ4FhtSSe5/UTU3qrj4bRLXcHDSZkEG9tlt2B5mgz1zwL+Nw6nVAzygc1ih1MZAPq6a0M7nOwON4u09EpolDJS6M7f6sKIbZI5pU437h9uUHTeUIaxdgZ9oERvDWmsXUDM5M65Jm+cTGL1+Cq64b8R/CaxZv65KW0TS9NEiI1nEys2wy0RnZdNrZh2skTYI8x0NwwvCLR2wlwsBVh49Be2wdaek430jmS974Rnr8ndi06fJh7r3e2uWb1Q2bPV0BF+7mXZ8ENn5YYvfeeGr30K5CB6WKgzfTDKVGDpwzTB3WoBM+iWqiHB5QZnaq7h19wVRqtzJZFpbVVjdeOmSgzHt/f9RltWGKVV7NY2z6o5M9YuvuxFKbvKLiZk7TWfrH8afGFLmn1MMNPR3Ydd7jWF+AjQ5kYpdP1GArnffkgJ3WvSK//x6UV/9A83n88PD8t3n+3/8UOPmpaPROHdXw==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="22.483870967741915" width="22.75806451612901" x="0.27419354838709653" y="0.27419354838709653" /></mxCell>
|
||||
<mxCell id="sgw_i4" parent="sgw_i2" style="vsdxID=45;fillColor=#FCFBFA;gradientColor=none;shape=stencil(lVrbklQ3DPyafXX5fnkm5D+osIStEJZaIIG/j05mJNmtPT7J2zDI27YstVryPKQ3Xz+++/L4EP3Xby/Pfzz+/fT+28eH9MtDjE+fPz6+PH2jTw/p7UN68+H55fH3l+fvn9/f/v3l3WF5fPrz+a/jL/y4rcvZjXysiv7n7Zvo0vj3i19v9r99f7ktCPcV1aVyXxFgif8R70bNtXo3imyU79/8SHej4QIbJTaqM/anp8/TXot3JcBe23avJbicca8jrHsttP287jU5n9a9luRiXvdK38QteOLdCbgsUfDsUkDw3AE8u14QfOeo5mJaHJVd3Jh31zOYt7Y92nClr0cr6rL7Oap3caxHKy629Wg1rOcqrmwOVik+1p1SMG7Ms6uLNfml7M5ViwsQ282VDOcqrrb1XE3uR85VXRjr0TpH+xl4dS2u4N3lBuDN5bKCdzcAuzsP4TJc7Fvsro4NvKRWwB7Ow8GHG3ihg29QwIN3Ke3Qm3e+rui0pgKnkBWghyAEwvAtSIgJfHB1E/0taQbeF9A325tqxSUI/1BMajeKNuDA0CQlZMN0fQk2PJjnTvB71otgWiNeA3/1rrtkDp6imSMjaCozt0TXt+k/iB/g/KlLvDP+qMp/XBay5JfgN4lx4YCreBkEBtFaqtQGwZ/+MkdwZGJT/OIyJOqRDNv7H8kVyNSWJewF3/Jfo3yB8/cqxClEkblUnt1/kGMIU3TNRAarerO8pSiHlfjzrgP+uKJ/YkAP90/O9nD+IsQk8F2N+K7pRhC+uS06CZBSDHoCls4kFhLAE3FDWU/TSZL4qG5FxcGMacXvQ+QO41MN7eD9XpRSWe8Qg0H0d2K+LVcHKtdhxae44mMwfqiugrA4CAmyP2TmRsEnctvKmnlJgCWKHkXECHqUbQt6dB7qP1nFrfeJzQt4nzgfvU/lw8cVnwpTRe7ToqepP7bwQzldSyfrYcl8QG6isSXrpboJMrHV1u/d1BwSDB1rpAm6Q4hA0DdlLwYXEjyreBqmDJ5FNIo+EHITcFK3cQWv9uSkk/OWblyGG6clAYWR0qiSfUYVz0gKHi7Ai7QtAh5EXgnVqehQ8ZsLgiPRk4zu20JPPl6xi7ZMQnSG54h4C3hd70GwRbOeYgdgGVoSgGWSdo8Mru2hkKxrIEdLYXI6AU8qIhk8syiZwDPk+NFNDQSPQPBHX7YtMMmqi6S6RdrZgc1NcAPpXfYs4BI8Z9VFlzC4l3qn4BXBvQal9tIQ7NRwlwtwDPZMUisiOMpKqsimsKkRgxeOnnNwCLiUXuMYqGrHTUC/HKbaq1+NraY6HI+JrrQdZUPVjjUw16aRinpjode1A7mewVzNbPw2nHWawSejYIGTxaBVXYjF1GtKJqjXIV10ltkMQaJQrqDrfn6qpyOg+/8ZT36FzdpeT7AYyV3qu8CawQ+l0X7sNC3RHEYCmYw0hwtiYxaRTd/WK2/kUQmmWHqTwmQUL7HDNoynBWLfL/yEkobagWr8VKC2EhvnjJvFwk6lIG5Z3juISypKISA2KprDCAIkaDP+X8tb0OGQ9q/YPwUzbTmMMCVNdJJRXMDXWwrmlio3gKebxWa3NCU92SwSIxmNgZvFMeYhVba3FJUZJgmE5KXujGJUoNG3FYk0mm/nnoqujMVTZF/zzn51bJW7OT3bsNKywRR1EiOqayPkatKRfBKjfRdrFVa102mqv1AUVKxP2tLDwI9k/zpnhXqnuxX7tquP2sne7YtL+xGBKTq0BKRrNgKOWiV0rE715GyVu//ThqGAjKHWDkV7sY5tRkNVkV5Te7rWPJh3a6Mk9nVr31YdQT3yvqZW0VpyuCFpok0opmO1c+Jpjq2TqLRVp801nHt4ky+6HRk86IBXiGgaDySx2vditAaVectGIYagwxnGL5YIo764MH69EKiHqAUebuD4APWi62xPkIc+dvEsIvJVnPFU0u6RhxHN9iTdPKONic6YqSxbHOPGLVMNM20eTZ5gJJ2rEXNjCOVP40acfZDVnimPOSbMG4P3K3otRlENWgZs0gI/LCh6vZj1Nx1tyumpNV/h6Qob+t6b6Udv9k2qXIw/6ArNsNPOP0Yx4zaKehyA0K0FmIAQMVyM+oc+ZU51CuKer2MSShVSbgqGSUvvnwPpChv2wwnryPHMAXmXmj4GMHySlxd5ZgkcV2fwXl+mOBWrGXTTFQ7w/SHZ4Oq9vlkyEzQey5xFXjf6JBSdLOlQ2YPyo54Qr/5gSvsst5d+tAZunigYH++JtpHvj+dGQLd0O5iZXn8TDNoy3x0IigMK6dBRFNeqywdXLKRmvlW71X7m/YZ0A0o/bmPO35lx0lFMGSUj0yKarusQVeb9PmyU36Ee8YcJYfeAr52e2PtNc1PXS7h6xz0UOngiGW6r0pXryKfBJRR9/9GRT9kc7Ghi2rLX/YjomNauzUjgZ+OzqtXM/DaYJ/VjWAvDY0MdpZiSGZiXXt9rQX1/YT9N69h+F0TH/Ha9Z89/4MwXU3mU7t/4Ihgenwav0/gFnCF19uw3S6nBZnf2eVj7uH8jmN581snXJI0wl/16rFdGln6zx/38kT7or80+PH36dPux2vz/+Os0+ur2y7b09h8=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="23.032258064516107" width="23.306451612903206" /></mxCell>
|
||||
<mxCell id="sgw_i5" parent="sgw_i2" style="vsdxID=46;fillColor=#2d5967;gradientColor=none;shape=stencil(lZXRbsIwDEW/pq9WEidx8sy2/0CjjGoMUIGt/P3SJU2xEZX2Fozd02vfuA2uzrv1qW2MOl/642f7020uuwZfGmO6w67tu0s6Nfja4Gp77NuP/ng9bPLv03rMHE9fx+/xCUOu0wjGjVVG3XIkONDxL/KWC96vfa7QJQFoqigRIkCdQ4PJIQ+25EyBANaUHKw5JXIrERcBwxI7lSBnOwVoOTu9YORwq8FaDh+FE6cjgnNLdE1AnuONA+843lgwyPk6gtKcjwaU53ydCv0SHyOEyPkRnOi8DRAE3kPgcBdAidZPA3vWeAJjONpzLnlA4lyCKFQHC1K0hrgoOsT6lImsDRBxenSgxNDHdhLHa6UEPcnWi/RkJqHbAQUhHauqElGi36kTgZOTbXEJbA2g8Jp6tBrV8c89n2w1zBqF0XUAvWh09+CzZLTJ1APXWO+YrRMYpMb7C24XfZY0EieTrde59nvaUBUe6uKYZaeFI3WX8T+73h5U4PBkK7nZkq3QcHqchd6vF8fpD4t13x3+t4nTYd7j226/z5+B+//l3k+h/M3A118=);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="16.999999999999986" width="16.72580645161289" x="0.27419354838709653" y="0.27419354838709653" /></mxCell>
|
||||
<mxCell id="sgw_i6" parent="sgw_i2" style="vsdxID=47;fillColor=#2d5967;gradientColor=none;shape=stencil(jZbdchshDIWfxrcakBCg6zR9j0zj1J66ccZx2vTtq+0usGhj0rtdLPazfs6BHd29Hh5e9jt0r9fL+cf+9/HxetjRlx3i8fmwvxyv+rSj+x3dPZ0v+++X89vz4/z+8jBFTk8/z7+mL7zP+9gBhWkXuj/zivv39nUO/vZ2maP9/GNwwHEJX5YcOJpX3nFeIb9ELO8IwksELSsIOS9By1KGMAL7AMmAPUGOPVk/QobtgaWH65d6NDmINII7kNSzSSDmnu16cNAI7MEeBHsyCyCOyJoi9eSYIXubNYcentIWzhBiT8+hbLxB1zZR7vHi62dau8FLz5cIPpmqO0im5ZLB5RF/Gk7D98719KgxaOjSRnJBRQEy2QvDsOlJh8lvkufU47NmaoqfGTD0eN1o6NohP+y8JHBsWi89W/Osc4l1oIJh14oV9DSZcai1uqNMYYRg2aoiw8aVHqmWInBPVyEzD+u+qmiZA0BjMZGAjcu4Hr02NvrA2U7H5/+3wc88U6uRh5McfJs/b/c0JWE1qzrLWByimSeX0WlKTqVCt1qaSs8rP2Mb0wXmPWTrJAoz5r3SRVFXhDzsaQAxOuZcD5JCD8UN1h4ajJC5GWIzlrF7J2ADV8fKtEld7LFFkKyWMqARslaWZGiiAaLxEYUVba9ab+QUIZncdYiMmGpdBwZq2LTREsvm1AzgrYGm+neqhRUzvC1kh9vE7eFF4E3hfWztKTOnR4X0eP2Tw7YLgbOntq+mVX2MW15YB4qtf2uUkZzOJo8NXPeY2kdfvK/xXbsUFMlRFUJNHzeay/Vic6v8BNLjleWMjUc94c3cTb5kzu4PvHTjeJ/56WaDPrRL6dPxdJrvtOvf7SVWl+YLMN3/BQ==);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="20.016129032258046" width="20.016129032258046" x="2.7419354838709653" y="2.7419354838709653" /></mxCell>
|
||||
<mxCell id="sgw_i7" parent="sgw_i2" style="vsdxID=48;fillColor=#2d5967;gradientColor=none;shape=stencil(lZPbDoMgDIafhtsGqCeu3fYeJuIkc2LQnd5+MrLMQ5Rx18L/NT8tJZj3ddFJwmk/GH2RD1UONcED4Vy1tTRqGCOCR4J5pY08G31rS5d3hVXa6KrvtsLTcYxSy3D6cnkWQZJ8Tk5O3qh2Is9SYDgHKCTZNhALYGIOCOBxCMAopDvA2hITgHwbWD6ZxYDRjqG5mm4rg8oyDkKE2I4oCAxpzBrwtH5tyTPcoK+z6ON3Cn+NyFPaKx+D3wJUqmnc/kzvlwszHrllw+Mb);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="14.532258064516116" width="4.3870967741935445" x="10.419354838709669" y="5.2096774193548345" /></mxCell>
|
||||
<mxCell id="sgw_i8" parent="sgw_i2" style="vsdxID=49;fillColor=#2d5967;gradientColor=none;shape=stencil(nZJbDoMgFERXwy+5Qin029p9mIiVlIJB+tp9ocTUatTYv/s4czOEQTTvmrKViEDnnb3Ih6p8g+gREaJMI53yoUK0QDSvrZNnZ2+mSn1bRjJWV3uPF55Jt+eYsKgi8EqTDODTnxKulRng/bKH2QI7Pb0AM4H5yAfBgs8LOMfwK9gBFtm8AP6H2QHDJisrguljRTixYGfjL63iofgGolZapzwN9+MAhVEKHy3e);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="4.3870967741935445" width="6.854838709677413" x="5.483870967741931" y="10.419354838709669" /></mxCell>
|
||||
<mxCell id="sgw_i9" parent="sgw_i2" style="vsdxID=50;fillColor=#2d5967;gradientColor=none;shape=stencil(lZLdDoIwDIWfZrdL17KA14jvQcKQRWRkgD9v7+ZiBAwgd+36na5tDqO0q/JWMYSut+ai7rroK0ZHhqibSlndu4hRxigtjVVna4amCHmbe9JHV3PzHR5BJwC8BuEZ8gh4It4vp4DXuhnhSBxojyASHOVEIJAn8bKAXHn6AyzD09nlCvnb9rP5n2MnMYddh5EHDit7zg+/E984+ybugq8lSl3XwVHj+txC7inYj7IX);strokeColor=none;spacingTop=-3;spacingBottom=-3;spacingLeft=-3;spacingRight=-3;points=[];labelBackgroundColor=none;rounded=0;html=1;whiteSpace=wrap;" vertex="1"><mxGeometry as="geometry" height="4.3870967741935445" width="6.854838709677413" x="13.161290322580633" y="10.419354838709669" /></mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
BIN
examples/output-cli-improvements-deliverables/business-case.pptx
Normal file
BIN
examples/output-cli-improvements-deliverables/business-case.pptx
Normal file
Binary file not shown.
@@ -0,0 +1,289 @@
|
||||
%PDF-1.4
|
||||
%“Œ‹ž ReportLab Generated PDF document (opensource)
|
||||
1 0 obj
|
||||
<<
|
||||
/F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 6 0 R /F5 12 0 R /F6 15 0 R
|
||||
>>
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
3 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
4 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<<
|
||||
/Contents 22 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
6 0 obj
|
||||
<<
|
||||
/BaseFont /Symbol /Name /F4 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<<
|
||||
/Contents 23 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
8 0 obj
|
||||
<<
|
||||
/Contents 24 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
9 0 obj
|
||||
<<
|
||||
/Contents 25 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
10 0 obj
|
||||
<<
|
||||
/Contents 26 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
11 0 obj
|
||||
<<
|
||||
/Contents 27 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
12 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
13 0 obj
|
||||
<<
|
||||
/Contents 28 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
14 0 obj
|
||||
<<
|
||||
/Contents 29 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
15 0 obj
|
||||
<<
|
||||
/BaseFont /ZapfDingbats /Name /F6 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
16 0 obj
|
||||
<<
|
||||
/Contents 30 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
17 0 obj
|
||||
<<
|
||||
/Contents 31 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
18 0 obj
|
||||
<<
|
||||
/Contents 32 0 R /MediaBox [ 0 0 612 792 ] /Parent 21 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
19 0 obj
|
||||
<<
|
||||
/PageMode /UseNone /Pages 21 0 R /Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
20 0 obj
|
||||
<<
|
||||
/Author (Carlos Mendoza) /CreationDate (D:20260412224013-03'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260412224013-03'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (OCI Architecture Proposal) /Title (Mercado Libre \(MELI\) \204 KVS \204 OCI NoSQL Database) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
21 0 obj
|
||||
<<
|
||||
/Count 11 /Kids [ 5 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 13 0 R 14 0 R 16 0 R 17 0 R
|
||||
18 0 R ] /Type /Pages
|
||||
>>
|
||||
endobj
|
||||
22 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 589
|
||||
>>
|
||||
stream
|
||||
Gatn!?#/1K'Sc)J/)JIV0[9I"m)q$K+=pf&@X=:YeQ*FrgWF'=,@`rea*(Y;X:u"/TOS;#o/tG57mqujF'\s@149#D_$.+r\7,fu$<PpIa,KOfE,ED#M3[$6.7>o-[okMaa-:+4J`*aqT.uNtP#b6nV<MnQXMjb?P"\-^LoMtESPYi>7_1i?^f)!jfh=sh;?`pWYr.o=9W/^QnDaga:.:@k0Wm.F%;p*:/+Bn3G.:[+ETq:nM`c3K$b#Zc%,#i8k6'Xek]jl]Wq(&/NfMb.=10N)hUepp5i;Is+3T6u[Q^@#BWc2RqM&8KIG"GJ[I?n5@&2BHZl<9)='^a<*q3j\Jc4\U7r<M57aQOmUV&eH=,EOBLYZCO1ld<CeoY@-1#B8WRlnH/+h*0GWdLIWD!'>NX6&L1"o]43bnGoP4H6*=9N*W41d\88+1.K`A2U+#GhM[ApM4Su0OpllqXrYOQaX42[WQNZQ$N<0UjTA4I.lRKbFcH&iPW@2HA=Ak(l+$2n&ipQVeC&h4S@$$D])0@?T"(<ru].4%@(jOm@(olZM9EK@.VNL;>IrAZIoH:G+g";:IHr7"8`DtP5~>endstream
|
||||
endobj
|
||||
23 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1866
|
||||
>>
|
||||
stream
|
||||
Gau0D>?BQ=&:WeDbfcTAp(1`UnuZg5BX]R0"%g!!^l,F^7)bKl[V>!0hiW:X#fJ<rpMc"Dm$[Z]k0qPQ"DmuZk'*$k9]g<dQ2mU4?N=LMKD@Ntbn%N/=FOX>+U*f#bU*&2Io3_%G<k-a5mAqDht8)qf+#qRJ_<>a0$r<=bA3>Fb].@<^g_ulSdQ<K,-DGkW<GfpaXAu4.?#m4MKkZ/\\(c@Y"':@kO5T]]n6&]R(q35[fqV(q;.G,8Y.ME/@&1EA4siJm4baV7VJ"46^Ik\cn8I=l]\*/e4uFnJ+\\RNoa(A1p@#`DT\:IkT3MJZ,0o7j5[P1#uI+;>6:.YSQ<V6_7);!.+L=&2$=9f0crP(poqFP82chh*PHSlZhB4oQUYUP6r]HB:;Er';m,O1f\EasKq25g#6Gun(m>iJ'PZ^f;ht"-51ap9?MN#]+U40b2QC8pSm<]Ll.jW9FFtJj1fYZ*$cPb9!/FMhL!6lCUgto!T"rC]B<Y-U\]@bXGm;;rB!%u+e,,*%q<8"hU$cI"`9:OCearof$#@@qJO_1C$?5?!gU<g:2i/ra:Ah;#(AEms\QmtO$H-BsU9]<*=+u/S>:U</a9VeJ&6X+)#X"$=>_u3G.<l1-*[1;XUq+'l6lSTK.bskQb8#+ICK3,?8tJK+5YM`Rpf9t?6:IkooHhYd65GR6=@5@_0o@Uua%r_6XOIH0/98[bOfKXG-tKnaKEC4FUdL@.Yt/tE<qdHu!^eK>50CB1PN(DHqmi\=?/h9O>CfBD8Ym+BHC0u]<Z_kg\Bd5kBV7):CV)3a`oK#IIEeBY7]n35+0qZ:$jJ?aWqk#"bmT9Ef$`/hpBZT0Yk\ci#M,ShV=JB3>$#8g-C5-tl$Y!Y,h#Od]YWBQS;`kq^Cerc&?7UP3KT.j0-5lXM.c"u,+!F`cj'pG\<?bZ-F2tiL5bmp!kR#Fp3:0oTs=_ql0`9S7:b/jL'UP8s+.2sUbNRMfsn"V&W]ro0OFNL(R#Kjng*H/QkMGH_OE]gDf+m"CU?rE)NoFYGPJ8D$Xhp`bka[JpP.+9SO(EIS?&L]NU#SdBD6H[4;jVa-grd2ZcdDLjiAI&4UA_b9<d'l#c;kUVgFjth.@_;%@k@s-aQV3TBBjar*R3"m/"\EF"=8[Z'Q61%`@*lf+sm]`Y3R@6lX?#h.5&<k=u^;jE6aQD(:S55M9$.gsng_EGk(:QjfC-m>j'#9r9+sR<W4<CgoND!1ptP2:EF"0A-gqWU&r-2/cm61@D&\WD&M09;g?_4i2Ha;X`-eeRj[g_?4.-R"-94K!Kq3_3pmCYklV@:md_YS'J6J+JO=f%o:f21TX2FU&trW*,,fUoD%PA$Cf4":\#g;nV0QCfPQ`1aA9LsbrbT+;tIDqf'?S+=GuW9ZCcqtE?O#`hcD.H"O+g%@#Q8LK=6#apCbgG"+;hB]te^YBuHIdl0d_&Qbt-W3d%.dRW]LV/t0RXNFuI)'/ui6rK`&_QX&>n3KNo\8sjPU[kCR[fsFg4V:>'CV"XDk`"T^`Z""#`WI9?SX8/[,8f:sG?3Kt:\uX==!c9he:GsYKhRRUZF0Q0>hgM@OO0QoEVU*M?qQ"-;@ej<$lt9=^r]ptO`AA#'p]VfFZ,?WHQJ*FpRO3ZS+tg<]X=F+E4rB5$fPupZJmE_gEcp-g!nqZKJE7(I)aF'=jL.A`_3!SVoGGLg4i3!YhBhl&Y*q]J^K^Scs1\KPIt3sTPa[?eeK)6gfm;uCNkP7aIecNp[<l_r8)$2\mL_oFL!3q$009o5GWP$a<O;$u3B"9[U\1X6J^)cG7I$/IR5B)!%H9K53ektnS*V)hN`EHLV5OXa.8Ed'>k_6&1qgF8]l]]pK7<olX"Ro~>endstream
|
||||
endobj
|
||||
24 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2750
|
||||
>>
|
||||
stream
|
||||
Gau0E>?BQM&q9"FeB=GN+VqZb2J6>987kC8+Yh*Opn]ROm@Hj`7kL-?J,OiH\l]/H_Cdj=@+"DFY,\\jX")(5(I+Mi*@4*lDWp_`8"NL8$h?V3Umk#'HZSi>a;GEB@-!O3&&Oon&,sbM07P&=FF06M0;Ln;:C6]?6i.SHjJW\MA8*9d?O:ejT]_A&E^J(koR#XaP1LXL[c@NsV32R,%jf`9P$''mRP*,AP;MZ3]tM(G*ZrkU5BQK9bA89mHHr2@3ddgRKpp1A=!DN&ECTA0kX(8kl](`pBkSU@,c=_u'X3\I./Wf>>31eH-h'LoLX+6rG:f,DJk%B^4_HTfD'#l:'pJ+_rRQPG5c6fnGA5tETMq(/B&:>lKd3N/Na+gcQC.&SjAO():Yu<Ugql6cM`U%LW+EP]cb5hEUZSG>4<1g34W?I@RTpWoGbmWt<'MA<h&\c85.%$/e/Jh;?=hZkq`EtHf:u,WR>G25<5A)T=iW!iq-CD9(>Y[`mgnVCP7*dU,#\2X:.Ah7'hLc=K2j/V7CW7gV2J$74=d/=aQ,W+L[Hh(0qb^>G0bi(oM4NF/Xsg`7X<1OFflAM+'>hq)<EA?Ah>78:_DOKm!GhQSCSn1ATep+Idi8Tld9'LX5f\dW)O[&8B+o2`M4QA@;!ofe8due,?-4+.`McuB6p\d.NEJ'ZW\h&6U^`9>D(jfdUF6_]*)qjn2Ba%HM3fFApf$S4bFdn:qoPB\L\D*^K\`u>_`ia++XH:@C)Ye&p,Ya\3$#bpi=YhbotP^rR'2YO6O@DaaWVKhl>aAb3Y(nBVf``;ij1[=?1YRnE+%u1Y3V-hB/[gWBCJnqZ/mK[NEQuqn;/r18of!p25^tB;3gc/A%<T_Pd%jm".Fdalc<c2o.g_IiF#]!7nQL,L#=#');V^_OiZQ#%=1h=qn6=;PlfdnS76/`0uNZPR'`>9pm"=amIWBo+)su9GbdD8Ho$a\F<PSg#PIGg#,XuA^6N++p,"dB<,-Uff]LM%-gEh_bd@u\Ut%GkmSct@KAV#M0.%2\j=RuG[Q*5R)P6(jgZ3S$sc7r"8@\e>[LoBI!=e,]PF[/FL'IHgh)!_RfH[)c37`5=k^+:n'Yo?)'.I%Q;lr9eDrXmohUWAH%GkHF^;:f)7iiDWk$l!DW"ZfcD6i"hI_RAM?FcN3QReajI&c0m!>F#0%1*lSai2kVou8&DfH*1(<AI@="dJmHO*%*h@bn_#[1b"Z(TRTZ]A<<>j55('Z:r]d%t&$q2+XkX[:/+Q]-2<SO.E70;$>KW'fpbK,fIYl/aZ<?!?-4RbLt=&;!?tno^WjFC"g!-EuqKL>2q*qSRc4:OB7un"YrNqnqp$p3X^9oCes,[eos>C;7f#U@LB-H=U0uDqa^#M8W\q27\-G$WU"jeWS:Y_0H_6Ds3tZs'J0DWIjSf2s&b'[6`XMKDa[aUXADXADC2gh:+X":atrLD38-]))j0gSa&TZB"RI/jO6VpFj0g8_'gp!jU^21kmYkkU[qMn"i`+![73eK.o`%nh#8qp\f24tZ:u`!!e$<JWWE/)FD-($VE66oX(ZDt2UXKdBTJQ5RDnq^_gQ]\@qU.8XS)<s>n['?Vm"I0(2Ig/aqdr%Z?7B<H7i^jE>fraoNqsprH3XMW@Pe0jm4FDK4i3bIXIR(?Z@YsM9,+pCd_s])=7;JeCece0#h.%(I]>$dJ[fm!NIX+l_\'2V(aENHJA\T.)O_bgFg\hOf>A<4p7H9)SQ?!FuE]JiS]%8WlJ(?doKDO/[hq>aS6).T\"f+]EY=I]i!og")_mn-@Z^ZK50OWi>5#j])"IuEE^"r;#=fI14^blo!lTqhh]8$Ae>,ZE^hf]3Fc6iSg\Y2deKt6@4"J%j9U<`Bftde&(+&4,$W3[rh+^LVT/oBm=d3YNGT#;qPG9r&tn*aM*tUX0@mA)=$59M<:GXg%)Dh@3Ss-j?__b].$TrZXGU,p>@#0gRRo!W<]B?kp"%>=b\_E8a35D^D(/EYmAeoG=XUM_+#/B:MK`>`.l.)2Edo8^]b`,kjc%BX#R>Hu*,2dKG)YW'U"?s2p!E8qK?@,c]o7P$-c)B)ABtc3'BWFZ8^Sj5*/tU<k_-9\P1mK0f!i`-`hGM:E_Z;l]"m5t[QEEGfW?6Nd-/58Dd`G[N9ck'aqF+I6<+_Vi;hu62+1-65Vp]MA2o=SJg<,!0HsRPJhq9!)C(S2@Qa`pSRss`U-j^9?.X'dUCm@nS(m+&C1WD_"@P3/G;ut7Q9]A(_$T%WlZqWgCg0YJR>LToECS699JQH]!H;1ucJ-ol.]X=M5j0,FMo&S%ErH7OH&^:o3-kA0'UYG4%#7hXF**Ae0$YD+[0R]`<-`T?M`J:NGHHWhCDQc[WWgks9'=a(Xm[4c6117Bcm#N*fJ4=a7HC/Vp'`L1;4Kp)Jf28bmSJ5m,)nA"mi(+=9.,4NkPbk>Jj+RO4<n[UB85du.B8]bj*$HRl!+I8I[>p[_tWl\`0O&>?<TH+NA'%(ZR/Z_CL<m]<>BQFhk5:*b0dnDYo(dq4StR"(=u[Oa0"58hdj_g!@/=HN_hIllSSsRD\#sihu%Fn`483U4["7"&WnYq;V9ZJ?)"qus0^<^fiP)ZIV1/KICH]A<4?$#(V*5`5&B-:h`j?q59ApBSCjO"T6T(mkAO\]?#a(qb&8An%/a_fhlcNX?*<`sZPrW3.\>p**idC`IVMn<@TTUTC0&#O!^G59c.6JS_T"%t/Y?d;5MI8@qCe$87D8~>endstream
|
||||
endobj
|
||||
25 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1731
|
||||
>>
|
||||
stream
|
||||
Gau0D9ip(1&Dcq.B(_Vd&S&r?bEPgq$T'.iDj?;lMaX[a\ZuVkrUk)>`?@M,5jP!]YTc`84.87"Wt;N*6^n$H%e+oO-Q`U*$F<qZY3!Oe'$b)Z5E;ff[%3#)70D-dps@nHgmfH`\3DIYF!:%#aMIJbVNo!iBO`[Eefr;p(pdJfUQGqM91[uf@%en+"X'.X!nfhR$oX;i(gJe``2S8[^5rccK<)?%Mtu,:0`)'\GM;3I7,h@#^GG[b'Xp29L#R*\1W>7<.'sRUA<Y))QboVn?*_,o-V#+1:,U9\onl5!j\Qb,BS?o*8\ATlmdYrC.ggJ)O%RMMTJlIe-@EerZnm(K!pUo*,_+P:#Ee9NZ+C/4CWj*TioG`E`jK"d1#OX*`=6d)#X3&HSUnUI^0JM<0'6<Li#,U3p]ngOMCZXkgos3%0tDadmjSm!MaVWA^o%Zc(!XB2.I#bhDuXm*,\ZT4a8OY)LMF"3WnW9ngAeuX_)4e,AS!4>3Dp'+"Vi\V)&l2VjJ"p1:$7Q&#aiPQ-K]7*<_/U6;dafh<lYQf=>5j]XV9NFO!B`;j/`=[o&]KFY/U&!jdW:+Tu!JcR2YVtdTFIJ[`j!ER"75ZU8m,e(K-?P4Q]'9pKXh>YZ`b8Lb'D#5c&"mfQ%En^k/6^\%H)tPbM&C%;lbZpf/$_<HSMZWShCZjlC%I"\nro\RaFUb3BD,m6.?`-ApsN2@'?Vg^#^ONGOQQCP%Btd(r+6H^JqC,T<QNm5rNZh[VuDLRoUa%R-@rS)G3`AiN!!E"!V59L(IDUF(G3HVeRaJfbmn]/+UY?l8CS!$2l#.14j`]j!aXDh[0=fUf?Y<JX="pEt`+LNqnZL2@@X?DFYD=nK1^:7`B3RgJK=PE*>#kpmFQc,X)ik9<Q-:2'^#s-rH;e=ke[Y<38MpT)iR\I)se*c=*V/5K]u;OsC14bas*Oq0d9[lLj[]>r:ZDL6&)L<^$f'db*N7s4-!naC&X>Zchd<X2aSb>Piu3A5-dp93WEF8!p]H7q_WPO215S0$[Aqq%cc]I=8YA,$lJZ":fIk!4lPfoGB^d=M)l`FV6lhmXDXW92%ERmS/7\q%79?$Ft_HL-D1k2ippIV[,VkekhVqQOE)#dJO=)r4nj>8*#k/S!J@[P+jWiJ-S5VR:^>om$l9m-'cCbOrPt'\8Kp[5>`m(Sm#17DcWnZKleL.Opd2LPtsQ+5OAUBI/AV$&tNk<4D-lK<FUT:;)do?1!JpS!+t.'\:7e$C),C`EICuH"M(u`='o@3([6&EDdsP_QZg(UWE[eB5<<=e82W8)f_cq9uil5JgV[himF!JV:&7[BOi9i6tS]L.,dfJ^9M4`!n)n[(Poa@nDft:HQg.J/k(,0INnS.<c=r%7DY4f,_^cS?6EO('ko+AL\fJMCq!2*;^UsX_VcD2h8ei9(7N.kVZ/>5B_]a9:H+s4krHgG_p$5INn9t6\\XrB(AcS^EER2QY8`fEoKn_G^)!F;;lj4$kp;m,\)OJ[jLR0L0nj2Q6Ga.#B@A$sr*pbD@3-50Int39<unkI6_j?^Ju12R1+k&ZdEO;A5V2bM2]*1\]nGN?i.Y<)j@JHK6*IHWm!)XB8JnjuU0b"F>+OS;`en:93E)(gSHL71dl4F&Z!=`1i]>&??taf9M8Je0XYs<5oB*N:LJ;KO8nA7e'[bP3N8h=J0Ug!pSAA?Ja&/co5G+HTo&>qDmZ]@JrDW@j8,i[Hm*k_~>endstream
|
||||
endobj
|
||||
26 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1085
|
||||
>>
|
||||
stream
|
||||
GauHJ9lJN8&A@P9Qt&G![3tr967E1>6jq2?Q`s1-W(BT>"i7BTlm-HA,6elu[G$Ua`h)?P1OcS/:*1's<u&N/,ojZ4+:sjj+=*/T4G2,Eiqn<Fb;4phcq#JHiVt'KGeHB;\Yqec0M4\99%bo0JWG^4SFt8LdmGf91PJR*P<p+gJ5ISc%('C>!\nL?":U2<3-nZ5X8JuKZgr0A^u`tUe$D!":S,Am)_@WXR+$aU0r$+S:R_-k]IN3Lb\nh$R,cJ4g4nY)Bqf.U^f+]WjHTH_4fL.5?WQAGQD"Ggb_FB5k?eQm1JCV!B.&n8hmVVU+@eRtE'`$B,Y]dXHWjF`B#:4(Nj^,PVp`]$B!e>%Am5b&kW_EEPgerrPRu*!oa+LLlAV<Cfe?]L:T$+E:J^HS<<b)J%,Q3P\0h_hpA:8\&GM`^H"pOaN_\m^A_Y]L<GdBRPcWDo,!R:HZ7O__W$4$V5:Z$C]ZWP&lXE!r)_&4D<:'?,kFWr<X_%:+\8TsC:#;.0]bR#lARf^KUq"Pta.Bm/g5!o?3ek$.EV-o>*;d92;Uj<%)EP-T*aI#G'q<`&Y0'c$'j%VSWnY.g3*pf'9;c\dWuA8]DS,UngTG&E[`?d:_\CliIa)(@<n>l>^@'^e<Hm'7G_m;E]Cpg-Y%-Cta"c*1J@+1]pY.prH-j2Ra;>B!Ph0=G]kPs4+/\\USTT7ckm*[tD=YMtUCB__jZ_ASglLlUMG15TC`)$@OT+"k2%1R3(4F2TWuhhSMs\C1VPWP7%bl/8rr1L$W0eRd7*&1[)bP;%X?1ZVgQbe7H_7HWJ1<JYrKf\k&32WUF^DSQ"P?@U%%KhmI&bY(2,PoqV8PEO@S*+'/#!r8Ke=ZP]Jftj`;1(`P"qjl.\g+cVSnq<a*9-e%bC5Lb(KAA`2'tA7Bo6Yh2%Z+bU(f!BFZh^<&`rXkoNJDeW!QC9.&2KB[:=Y<&`t.pE#5?eW"7Ucm@5%W#h[)WZ0>*U.VF)nJo]hkltTph2(>>nt`j:)oE:HWGY,M10o2:p0JLaWG^coXR'p#%=q)nj&ZqQ-e44"UDT@mWZ*i#AWk3UcRgPIquNk-PX>~>endstream
|
||||
endobj
|
||||
27 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1004
|
||||
>>
|
||||
stream
|
||||
GauHLgJSqU&:N^lqB;h)9?4SM*YUn=)DJ*Po!6,I:gaTkV"49Efk#.Lg50Fag4Gm/oJq>f3AnJO3$+gl+3afB&)cZH!$Pci%72i[K._6MX`#fR4BFfMP>3'JVg'NHi_rLecdj(p#%oL2^_gF=VJt5B_"id%R,*9IXc*Z,QkmPA!t:<FENm*4#%HUj$!8+jT\[eXUMO1#GB1+8@G(!j\gPD/4W)tk?pA*Y%>A692N3]Tq=S9gce"@sg+Zrd#LCeW^dYIEOtR%p,\H>/<!91P.Yn$CPmiO!WBkjm9BZ0)9b-lR8>KY02dUsB=AG_9\SN1S@s)MobJBm7`F?iUM96!V%V^\1$9W=?j-&o),C3L;?55ZDe/et[+Fh26bJj.TEEVa.Enuj_Ni1rAO^(APjEe$[rZkE#,oIr<6qGGM-b6`\agIqSN&Rpul&G?b\IM1`P>jN_H5VuI39Y[FUr#uj>Wf!)N%$CHP6qP_6Z&%P`cmS=-e42:aeb0c"tB1J,h7m5i_gr!DQHD^T2[`pa^p\$L*=*L;VcRjEiGkG0d=.r;V`JYTaXM8@mP.GUq/k4AWuB`=YHb<lGeM<P-:c&;C'eP?PJh48Tf[@pPO8<mbV$kX<VUu.i/o.I*i+#p6sX[Y1Cs&XXCGk:$s'VgbQkr?,.o:`m7;i)&aqda$05@*]CpE+WO5q*O*Z9JKpVd@*noZ@jGrF1`W7AfWANL,=Xeqk[HNF9W6`q>hJn3!acNr/ai5(l?kDg0HIJg0us"ea]&O!R=5HaYF)N.:7n+\'";9>-,=043oAaEnC"+-Os#p`T/V[]WFp8#KeLIoE)p58G@;nrK?c<k))["p0np57GV[.H[G?;?L[G)H(_aSoQ"%S%kF$Y?YrCMZE6eKHoH[CnIti)h29f2-i-5bbqE7sAfc;&@d]1LWa3>j#SDs#2+2/k_CLL8H"rtQM<A-.WIj7/=O2"[XWpcl)9@[rhd&]"*7U'ru*%!*uW(*6]kN)`Hhc2rge,~>endstream
|
||||
endobj
|
||||
28 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2226
|
||||
>>
|
||||
stream
|
||||
Gb!;f>>s99'Ro4HS-Rb>]>7&/]l+$e\(`1(-/6_jjMa([h"m2A*>neS*r2Cs*E&0J%RX`:l'tQ4VP>f@5k'P@s1/6H?j`h#.8U5t>G.FZ_/osLe"_DR'[n8+bs5^7VGmC(Ikg`hiJ>>1;$a`;VJ\X!\o)(T5$T0Ei[c7t<fBA4U8^2[2,H,%9g]-h,uNKOpeEB5"f+h"[O?[_LrZYSO'q2-`#NC&dH0lXm*-K:IY[/l+g\_@lAB:4(8"+UXZ,EOl8a<'M...Q+pc(5e2D8=<q[ZEV!-p3<$<OE<;-*n]4/4KW([;*.96XjinSN-GO0u[`O6\KcPEeK"!c$'/GP1\Bc'RRFi<>F_IqA/\n30$bpMX8/b^,,$H6h@J<'Lk@0FrU[r9Y<"u.]<&`'Z"'gK$Ija?d7q:>/7Dk^r7^B"P6(4U@?T>"CCc9dmu!F2)7^d0Q]:NHiE1-lYP?B]mo'J,si@q`jN:"*%!@CdF&HPD1u^&PH<1:'r6*@,nMV*%nE9<ok?SS4L`LfVMm*m3[Y6SgGq."2_;(PWZm]rUac0TN;#%q3JF$.il*MiaS(<'mI7PpG4$:amNI=^TcPQ\FP"+poKZIemJl)@4CO<,-sV$g]s3q8jnBk"@Z+U(GSnoN.SQQ3--7d6?kQZ4p<jpJ/rqE9TGUlFAU*jt0UlIYF&^F1;W#]Jp7Nm\1g-_6MiEUs$>I1eg!]]%Dk3o"A5raSCni1=EP6-I'CiI>m/-??h6Vqt5?lL[,K.3hoc6qVs3W9$oDS^l=KkDPJ%dS-3=\XL?nni3Mun.`g^PC3G6Q%?*f:LBUcspb`JT]=Tu7\TO=1i9^qY.=)1nJoq+[*q"q6=Ts2/r+3[qPjdK\84fb\l.N9kLh0\V;Q[-G>+1=T^DQtYJ%tI"$KpecOS)l<8bBi1;]$3ebHYN0Pp=s#[^fT><K4<7p%c4"/Z\Ki5Y<K7Gci;Je''j"nZI+S@O@?s;NG#CTN.$jjd8o+<G#o8XPg4SCLCYQfG_hg2kS^.*ZJ@bB][jdc+:mOldgUmo6A[S>73oNLmPFn=U#7r--<dTeHbaboK[h@7Gj&mU-\<S;1Cu[##:'?H;c/-IE4&#keTn'(qss[L#[LD'*Q^QqlMh8;]a4?2dJIn?EWI=_8COB0]%+!NlKkBT0C8$b$g,A[Dps)`t>#Fb!T:>d\S7*6`T2\Us=tG':>bDKMsWEJFgSNm(<KuC<L_p8l+`JJ5%I\\&)tC@-QcR:up!5hZaEl3%oiiDK^=pV_`Z%:,n#!chHCQU\!:i#eVDna#8=6/MU&*<HsSlm<KD#ge@egL9He\(6/]mDQ^aEUT\_c"O\]Z^cBFAfmN5hD;">dc'4SILj&:6eI\7i_Y7:IH?o*aV_m,]oqUXH,]jS<LP3\YT"BG*Y9GO`cMBN&OmdR%)WgW/X"?YN7WGKLj;(gD-h`]OI+NoGOMKPYCUeTrSKPK\[)+('*5R>c6Zk=l<ZZ4EWDFE1'aBGuI2O#gjWoZ)reCp-$PGWaq/q@Oek4+^I@K_COk#rocBiO0)I(XuB]'BJ=bV#d+Vs0.KP*c47MXa-M#As9T/qa+:Ju'4P=?@.??QpeSk2E@AMSi@GCFZ*:NGkfR!RcgIMtWOdX49WcdKGTAWE%Mm"F&q=t["!BXQa9)k*=@Pfb"Y1hET:V!'kEbr2asiTYe9)6*%lD_e<<0#pQ2eWF]H(r-M,F^Q+L@<0QO(Eka%Sp;YQ)o5?uo[8(>]5r.cISs.::dWmk-A>a,ftE_[9Ks;ZOI+m""b50i>uDC8Z%]14^X89dS7ZR\N3:1L5DT9O#W^)84c?/4?AR6cV<mcNSDHZc>1668^WsjZ^L)`VAUVbErUmP02A`nO`EdnWd_=,302"PJr]6p6DN;0+H3RN32rfML`M_P1E^<],F&j^R`l^41H_%nM/bF(;Fb=#'hPd<:NJl,'F:7?WW4J79TnY.SF;]@JZ'4j5B8]1u3H!#AjPhq19-mYu4h2;dkN?e+l8fTbs.Nk'cb<X[m[[lIF%-b[!CE\j^jRlk/XL$2f)_%!nL$W#$Vo.IM>rX2)I'oZc,kuYHjuOt%d:N`!.J49+TidspOUfm9rtS#B!!FNDO8W<B-/cQEC2[U%1E8aI[!0i5-l<4i+!sZkAD5],d>aW`6PVHa7h6mQjcDTe(+k@2:/G&CU7%LYu/Y!l<.k)_pu&G;(Nl9IN,[S7KcAS<P7[tG`e=N3;O0T-g)Z~>endstream
|
||||
endobj
|
||||
29 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2442
|
||||
>>
|
||||
stream
|
||||
Gb!#]>BAQ-&q9SYfVabbZ"X9PVfNnqfh'[sZ"*%ZiJ_D10Ek$]GYq&RXulUPB)u=,aV#gYFJe(i#d/^6`U8N;`KGb.Imj;Y`W-fb3."GO:`)uZfS0jqCUb9)rHVpu^1d`b%-lLU_2!?3E;/=I_UD?`NX_T?64An7lVRe[UQV1O\-7Uk1,EaiTn*Z-9o.sn?m$iVG`^2"!`H%o)<sXFoS,I9fd)8enW7b#mgZJ'#PZ9Z0`D0o5:`>MKu>].\$<H8-;uYXM%hLU/272^n4ck,0M13^Q@(hl>;D^`:R5HfCe>5QG?6W*%#`h)IDa[Zh6In'J&b;40`o*Eq0\<]#cL>N`e)P#SVGNsLS.CNXF*K"lIZ-;@L"6kc7XL!)C7?^)*>A,;ecBfFS[d3`&0\b)8pNCf>=Fl<_g-Il1cg,,>@U1f\Y;.$Nc;*=sKomaT^9LoP(HN2=`<+[1*>RgH!IQg*W<D,Ske;e$4^S,a-u2WTb;(;YN-L%-O;uO$X2FDt#^Yg<*6f`DF!M3Ng.-3mb8tKI4Njl0cuR]JLX2n)4."MI7iE)3Z7=>)eBK6,>3KnWJo)*i:1TFt7:AK-?<)lku[7#3Rd)UQq:]H\s=l1)<>!c3J=1,^X34U,PUghe-^1poRb9dXT5cJ*[aYoV%-73P^3'"cDFlRb=L(Rc%3L2;`he:q`5Bd9U*`r3XInD&/g_5uiQ++Z7flfCWP)d)`A7fM*E!ahh=r@FcF@+$OVqeQ#4E7@;c$42+dMT/@J<3YiC":t4_QVF&1<&7NedO:1)*NUh;Ib;q`LV*2?Q&)^AIqKraIbMP!&r5p)6$/@_fH(*M1CIh/22%WiJ:8#AGAK%a#OGB6+aBVNd_`<c\%Bu3O(*]0;BK6EKd"!*n'2u[aOU0W-`:&a_.^2rE"_oam)TITj00GIIA&MLccF#X/i"!$3s%+eB$2_LOY/EG;jH"QZ-ph6Zipd,C9Md=.Q'9_+/h_sShnNFha#A3]epRA.s7(L+$#ZrmcqLj+"Ui)>oZ]A'mRMJV*tNMSAbq(J2o_sN(0Sesq+F6WO(Tn8Wd/o_P9l,^T/%R8_c[?o--p`VGGV_gCknkOXKpi7J]k.s4k4:FS`kDZMpglAJifPWdNfV>,1:HQ6.&J(LFbaO:=dRO(OFe$XcKKS<!_2`@9$`e:ob!4T/X)?opu&e4uLT;dQVX]S50ZbmiOIDhOM<0'gd<Fi4NCYo]P$F!u?Wp@9`pZT'^')+k,$s/q_Lggp0U#0*LWKMr:SuTGT-;o2p];\BWGlOlOj*nC;F':.4!IgU7b5rS;*+K;?1,IVLd[lC(j[q!9eqeqcT$NEDo+#=$$QAC3>QB`A&OFs<^3L9q<pK4LFU>\;/U/hq+r1)\BPBtnO2\(e)")7t<Mp+s=ri"1r#(,#jdc6Jq&Dd(Kb!U/i;7N;4%/rY"*`R]'\L:cJSqT-#:>iNNcSs8%l&^^fo:*T"[LW`B1^&-[EI!>^b7NYe`.V615O>PfVB64b_#>(lK>uc=,ddKH-rI@$#k%UQR38./L#r`7)K8@:sgBu)>D]H?Rft,j:)qqk_Vg.ku;g1<G&_=Fud;lK_1YE8L\&[8Cfl$gjOh,6A4Vp!0h;0TL7B8Gn^//ksnLLUXePs#T\dbZF;sadSel:@rep<L6Zs$R!<\:<pW>=!F6W`PSI3j[64fRUZ:R:0ZWd7^q/ZgAbD84Ou2lQ2XHSs]#8`=8b2"+HE5lh;kZb"<>4lmbF8'6)oVTVB5K$m.]+"&TaaX?jI^iq=[dk'XF[X12\[^XAW)0F>g\.e[>e:&`bflEQMM'N?fm5T@AILQNKgk0M>DY]j>U5.Xq:%R<?ZEiBUritK$oMo]t*)!ur`W>T<f7+P(To``l/OSoT\T\S^cp4+<n^0*f9[mFAOW7j(%/d;jj8$4Lf,('b"!Dm+P40>5bcYumn[J[Vhfa;(+0UT)s)IPej"&AW]!<9EI_i)`KLoKP[Bp`4#s$UckXCe4n/@5YAFV<t5lP#/XBP6I&4r7/eT_kYgA2,eUFef`F^Pp;Y4YeJpM1AXD*!5@5#J-V_I1NS^2VEN@eEm%=+#mr$Ci4OR#&Db(;6[7^Cq>?rE#Yd'/fUubJa#jnc]QOEadG&"ZD6:ejKa*E(j%I?.*-f\D@&6k\YIP--Kn*W\ugob9k!;2DM@=s%Ou[>;c9'a?b`!6m:\?pW#>m,cS_!!t4:D5H==]#q=K(Q@g'qZ7oiM:h?eX0h':rS2n6n*;k$USZ(hhD5X7>#.F!ZDbn_!cT+H)QDou;Pt0/F2GXo[+jY5>Hqme6?=#mm*A)O8$RAt@V&>R?j)OT,D"Tg1e-omq&#l'<E.L[E0uLOQPY2bm:F;tp4iKq5E*JX`^Woj`7TmJ=GGD0E;4:MXk.LA54K-m9DTaD0F=o.Z3%."j3lEH3gg[XR6O?V-dj8rfXF;\b>r_[F\@_ne~>endstream
|
||||
endobj
|
||||
30 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2396
|
||||
>>
|
||||
stream
|
||||
Gb!#]968iI'#+6EoP)L:)GpY4Y!"eR1ZO<44-k*QiX8.@1<+\i+DHo1f5Ca6-'<NK&QZ36Z3>eEUHa.^NGai.N?=np`u2\53uEGk5UbF4J@LmQGF*8tGP(:D$:<L(-s/<F4b@&+(PUW$N[R"3jl!Z\GWoZrH(f,P0KEmdKh>NZq2I)OFZ^SQ@(Cpn^'>EG,$k7iXsT6",qVqhb2E&PbEsRZ>`,NAE.<7XIX,r5i<.m6%<oQ8R@=kHB*J:SjO5<FM1k&W@-PZF/$bqs7PuBZ6p<pEF[JI#]G?^+KG[Osq7W_?jB)n7JVI4(Q+LIG%ac=CPZUem1&,9&71.PArl0VpaNhf&q*aH]B8SJX:sY+t'fWF\3nJ>*)Wb]jn\ITj,AI<ulKf>B&`4'b[3M7bq@7u?H-Q,_)=GjQ%EDo5iFl9e1#"G^j?TMXN34_5`S^j'D$+0e$<`dsU\:E0iV6H<O.B"ug_SteU@/^ViD3^9C:RD&-%Y05mui)F.PYS$..WsO>L.)/MB(7t>e+:s(`P6u])gV@_(XR#dXud6&^gi.p),V?QWb3`ZWSG%\>M06\B#>WHIna0bl:g:?C'5H_TC%+,[r[lP34PQHT5tSW8jR[3"?k$#H^/'C]fEr^jR._B,A(Yo<XAT>eP36)g7"ik)Zo@'4B:pOt>0gS['Q.OOR1hF1<Yors]iM^tCJU=`O-I2Ku_^<Wl["?GMn:o(<Xj[oto!'LQ)SlSjgAnV>KjN)^:djao!'(J<XH>Egi'eMHA=$U.lGcgh3>Re@2C@),&!ZCK9a#Y#BjKcrq)f,BB:#;D+[lbC0[.L+;[@o5BS=YCQ5kPgiRIi7A3L/2&mF_M8Y238&DEZbUSI\X[E-Meo.ANVL(&n2V@E"I<6gXu!HWeYFQ*11#@s$*_LL__I95mhZqjNEPMPSd3FV$XCDHq,WW121BrM`fg<k59d[J%m1K0rKAq:LM^NBhNN%B?e?&bLSgRgS&4IgJcWU]BP<dPKflJ$Ct&4,=nj&2pJa08r229rN'^OWogpQ/8V\AQqj#4Ci%8'=5p!HFF,UPH1\N534P1nR&m:=n+i":`pi6%B0GBWBF.WcLrY#81``..pd%kAY':#3\<&gb1>2-B\@f:S?DZ>t!;7f"/Kod.%3]*Uae;@u=!i^$r*,?%n86)!rp[BBL[LWfXW*D"9^^6c2#6SPX@_2#2fs.$H\^C6<H\=8IskK;2CiYuA;7:"n$d"rqSop8IGnOP>%EOj0MM"CfY_ZaN/a!?YJBt*<76j^KOWt;IRd1to^oPH)ci:$TS-Mj(KncL7*"roe*.B/k:K1.V]n!WhXV;Kr+/@r+W0mmiP9gNU"3$"diF%d)_SBjbEPq?%kXguQun*kdN*Z:1HC+l5E/5q`1C9g\B4SL$Kna`Lm;<g\8fl3%^L+7-MG5s%\_M#F3F[YoLrY@0;c/"nP7Q-hOi[_DE5M$WfZH9Gjmcb'lH$^>$o8shcI_B[_>S?rAB?Z@FepHMj;PTlB8=7[F`*#gDR0kr3jpYpUP.5]C&lP\6=U?=D@!L9l%F+%>(HP0s1/kNbZKYcH^1C$"&h/GBe,^lk8W'780Y:\LSFKpe5nb[h_9>N8#6RZ-Bl`j4J842]Aj^YFN5r"Is.an??A^+%o_/X.qoDJsj#8</m`,^^-S_Ws&$^H&b8]9N3rb:f^\>*sC^%59?'#$dY3]eTK1+(Vfodma)dPH"*aDRL@bq/ohG_I/.$g"B(A=b)l6Gj@+bHn=WSk&&P*hO,%r!B1hd%>>TO6'q[-:*t)3s[CPg4@%K,Or7iC7Z7*nYjE&j)3>NI:7bN'jZ]0mi+-5_`6Onm/9iGpH5m35Hq>Q",J^dt-!u!00Z@`_Th;59j%COPhoeHiO(hD./N)E9C\uiCIYW:E@=i%LV1$ZGp#OtBkN2)Lu)UD$5\?lT+f#$?!k4uM<dTW-s\;8+;b)sAk^:fPP3BdRD`OMH]SUiCm^@6V%QrO!f)c/TR"U`BsdE8T"j(rL5:1HJCdW]0nC^otR=Zd"5gTR`Yi]6/p`e!b>io`NR3jNJ":74e6'#nmb9i6%-QhntbaEC)IJP0JM(IgKc+b;Q\2S+n81hBS/Q>iG$&rd-I,T&*Gjmjm7F/G]m"uYF9k4Q`k6Zld\nN%oK01rgcHuCrMNspZmfuCX](`4JY;+Oo/FCScg6u0p\/NMTm:,4D@U$pRu]NDNlsp#,SrP@M95M/6ErKL2j"e\/$O:2:/Xh0i!rE98ki.0E^PH9qg4JfmX.[76u*P'4O&@T_#V>9ecB6C1Qb#o>bqZjYDluq*e1?2t\)Ep;/Ohf!/WY%VuCK1"q$q"M:ee\)3_X&q*;q3d`hDG(g61n_](g8K7#)F\)GaSfPD,JW"n&d=Gl2Z`bDu3;O^](?=K~>endstream
|
||||
endobj
|
||||
31 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 454
|
||||
>>
|
||||
stream
|
||||
GatU.bAP3?&A7ljk*Yd+!J>r5)^SL[7"+luMebDR>K:VQXK#8b^-EYq&+rmFfO`%Gc2\:&%2RNB%:#g@S1lXWF9s:M5WZeBNSYnS1lVqLiCZZ'K&:Q1gdE,(;$/8?A:c\7e01m_)"i")ZPequA44A!)Z_-";i(Ws9M?qgPm=O";BQC@2$W[#k#p)@<^#+KMnsd'RkBF_Ub>7l4QdlL8YV@Mn>L2i<Db[/.]X(&`)*5.P@5jqM6j!Fi[kbQpCqt;SZ._Mf+g6'\5a1_UtoU_&rcfuKJR)EpcX&uAuci?o&KdimiH,&81:93KY+]UX7O'nX*u&SEg->@Q]i8<H=rCe@tXD6CL6PaG"4,[af0CVE8FQ-[B$q>PIS6$)FV00HrO>XF!a9B<&fSOpk(W+(hL-n2jfq+d=,[%`i[MV]#:Ob])pGnBsZ(8G58SQjbZf%5G78;DZ~>endstream
|
||||
endobj
|
||||
32 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 772
|
||||
>>
|
||||
stream
|
||||
GatU/?#LB2&:Dg-fJc\B\``k(8#TT>C.4ijfGE_`QPf/W@/GiPmo__D8Q(+m:aFe8G%PC,)\*1&G[.imi-c!"2]R&LD%AaA3OF!Lh9LJn=B-_OP6+CX]\p/ND^g)40MCBf9LFq0<Ko1(;:P+m^uK6,<sQ0gQ$Y9PB1:P8^iI`$Z2d?f]VrWK!eB_c7D]<K@=F9G'@O[e>$?TWq>L!BmF0#X[,7O))`Wn0]O4`b"MQY&<t_oB@Q8tD->DauA2FU29!VF:6a4LdK;U8^lqGCYs11fAc=j=_*MkoT'a!QJ0TpJ-eG8RuG8mRe8<^DC!dp]^3?ZHI$>NDc>J@\pX5,p%-/U.]Ubf3q32\>Wc]fafe%<97W+3'#7]5iJd3F#QG%iKiHJrk>A5DifGKsMULJd%"kqBrM,As:`b\.N$^Z*Fpm%9go4"E/@a_nDZQ$/.kZ.PaLH3MHBdN5ea$/U3#r1GmpDIJ5;XVe"haJnbR'qr8qR_c*j!VVb8d^5#Yr!o4<DN$pf7M"7m+f;fs&k9,0D*0A3&=oLU952PaAO,H2F@LU-3e(fUM?VgrU[fT#TMjdBT$bQ(C5J6gHpKV&(LZT&^OFU.Y8EM]/g.NFCGQFjTYM0Noq"(;=_XW,*[2d#h-.=-Ph7ET%$!W0:#[r=AeS]+!Z6WdNa@]EHYSaV[L358O!8obI^1+.$R_s1dWJSBpE=u4k6&G<LWj&JMpuG:`ro_,UJTZqTH$La1BYA`Q&;Lo4oi"H;8LdHip^bso*Vg24"af"~>endstream
|
||||
endobj
|
||||
xref
|
||||
0 33
|
||||
0000000000 65535 f
|
||||
0000000061 00000 n
|
||||
0000000144 00000 n
|
||||
0000000251 00000 n
|
||||
0000000366 00000 n
|
||||
0000000478 00000 n
|
||||
0000000673 00000 n
|
||||
0000000750 00000 n
|
||||
0000000945 00000 n
|
||||
0000001140 00000 n
|
||||
0000001335 00000 n
|
||||
0000001531 00000 n
|
||||
0000001727 00000 n
|
||||
0000001847 00000 n
|
||||
0000002043 00000 n
|
||||
0000002239 00000 n
|
||||
0000002323 00000 n
|
||||
0000002519 00000 n
|
||||
0000002715 00000 n
|
||||
0000002911 00000 n
|
||||
0000002981 00000 n
|
||||
0000003315 00000 n
|
||||
0000003446 00000 n
|
||||
0000004126 00000 n
|
||||
0000006084 00000 n
|
||||
0000008926 00000 n
|
||||
0000010749 00000 n
|
||||
0000011926 00000 n
|
||||
0000013022 00000 n
|
||||
0000015340 00000 n
|
||||
0000017874 00000 n
|
||||
0000020362 00000 n
|
||||
0000020907 00000 n
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<1a6aa1302ad6ba2dca92b79c88f91ea9><1a6aa1302ad6ba2dca92b79c88f91ea9>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 20 0 R
|
||||
/Root 19 0 R
|
||||
/Size 33
|
||||
>>
|
||||
startxref
|
||||
21770
|
||||
%%EOF
|
||||
@@ -0,0 +1,175 @@
|
||||
{
|
||||
"summary": {
|
||||
"total_artefacts": 18,
|
||||
"mentioned": 3,
|
||||
"likely_relevant": 1,
|
||||
"possibly_relevant": 5,
|
||||
"not_covered": 9,
|
||||
"skill_auto_generate": 5,
|
||||
"skill_assist": 3
|
||||
},
|
||||
"artefacts": [
|
||||
{
|
||||
"id": "DEF-01",
|
||||
"name": "Customer Profile",
|
||||
"phase": "define",
|
||||
"step": "ideate",
|
||||
"skill_support": "assist",
|
||||
"customer_facing": false,
|
||||
"relevance": "mentioned"
|
||||
},
|
||||
{
|
||||
"id": "DEF-02",
|
||||
"name": "Strategy Map",
|
||||
"phase": "define",
|
||||
"step": "ideate",
|
||||
"skill_support": "assist",
|
||||
"customer_facing": false,
|
||||
"relevance": "mentioned"
|
||||
},
|
||||
{
|
||||
"id": "DEF-03",
|
||||
"name": "Point of View (PoV)",
|
||||
"phase": "define",
|
||||
"step": "ideate",
|
||||
"skill_support": "auto_generate",
|
||||
"customer_facing": false,
|
||||
"relevance": "possibly_relevant"
|
||||
},
|
||||
{
|
||||
"id": "DEF-04",
|
||||
"name": "Ideation Workshop",
|
||||
"phase": "define",
|
||||
"step": "ideate",
|
||||
"skill_support": "reference",
|
||||
"customer_facing": true,
|
||||
"relevance": "none"
|
||||
},
|
||||
{
|
||||
"id": "DEF-05",
|
||||
"name": "Business Case",
|
||||
"phase": "define",
|
||||
"step": "ideate",
|
||||
"skill_support": "auto_generate",
|
||||
"customer_facing": true,
|
||||
"relevance": "mentioned"
|
||||
},
|
||||
{
|
||||
"id": "DEF-06",
|
||||
"name": "Value Story",
|
||||
"phase": "define",
|
||||
"step": "ideate",
|
||||
"skill_support": "auto_generate",
|
||||
"customer_facing": true,
|
||||
"relevance": "possibly_relevant"
|
||||
},
|
||||
{
|
||||
"id": "DEF-07",
|
||||
"name": "Value Story Delivery",
|
||||
"phase": "define",
|
||||
"step": "validate",
|
||||
"skill_support": "assist",
|
||||
"customer_facing": true,
|
||||
"relevance": "possibly_relevant"
|
||||
},
|
||||
{
|
||||
"id": "DEF-08",
|
||||
"name": "Joint Engagement Plan (JEP)",
|
||||
"phase": "define",
|
||||
"step": "plan",
|
||||
"skill_support": "auto_generate",
|
||||
"customer_facing": true,
|
||||
"relevance": "none"
|
||||
},
|
||||
{
|
||||
"id": "DES-35",
|
||||
"name": "Solution Proposal",
|
||||
"phase": "design",
|
||||
"step": "confirm",
|
||||
"skill_support": "auto_generate",
|
||||
"customer_facing": true,
|
||||
"relevance": "possibly_relevant"
|
||||
},
|
||||
{
|
||||
"id": "DES-36",
|
||||
"name": "Partner / Services Proposal",
|
||||
"phase": "design",
|
||||
"step": "confirm",
|
||||
"skill_support": "reference",
|
||||
"customer_facing": true,
|
||||
"relevance": "none"
|
||||
},
|
||||
{
|
||||
"id": "DES-37",
|
||||
"name": "RFx Response",
|
||||
"phase": "design",
|
||||
"step": "confirm",
|
||||
"skill_support": "reference",
|
||||
"customer_facing": true,
|
||||
"relevance": "possibly_relevant"
|
||||
},
|
||||
{
|
||||
"id": "DES-38",
|
||||
"name": "Commercial Agreement",
|
||||
"phase": "design",
|
||||
"step": "confirm",
|
||||
"skill_support": "reference",
|
||||
"customer_facing": true,
|
||||
"relevance": "none"
|
||||
},
|
||||
{
|
||||
"id": "DEL-17",
|
||||
"name": "Cloud Operating Framework",
|
||||
"phase": "deliver",
|
||||
"step": "operate",
|
||||
"skill_support": "reference",
|
||||
"customer_facing": true,
|
||||
"relevance": "none"
|
||||
},
|
||||
{
|
||||
"id": "DEL-18",
|
||||
"name": "OCI Operationalization Framework",
|
||||
"phase": "deliver",
|
||||
"step": "operate",
|
||||
"skill_support": "reference",
|
||||
"customer_facing": true,
|
||||
"relevance": "none"
|
||||
},
|
||||
{
|
||||
"id": "DEL-19",
|
||||
"name": "Retrospective",
|
||||
"phase": "deliver",
|
||||
"step": "improve",
|
||||
"skill_support": "auto_generate",
|
||||
"customer_facing": false,
|
||||
"relevance": "none"
|
||||
},
|
||||
{
|
||||
"id": "DEL-20",
|
||||
"name": "Value Realization",
|
||||
"phase": "deliver",
|
||||
"step": "improve",
|
||||
"skill_support": "auto_generate",
|
||||
"customer_facing": true,
|
||||
"relevance": "likely_relevant"
|
||||
},
|
||||
{
|
||||
"id": "DEL-21",
|
||||
"name": "Customer Success Story",
|
||||
"phase": "deliver",
|
||||
"step": "improve",
|
||||
"skill_support": "reference",
|
||||
"customer_facing": true,
|
||||
"relevance": "none"
|
||||
},
|
||||
{
|
||||
"id": "DEL-22",
|
||||
"name": "Improvement Actions",
|
||||
"phase": "deliver",
|
||||
"step": "improve",
|
||||
"skill_support": "reference",
|
||||
"customer_facing": true,
|
||||
"relevance": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
BIN
examples/output-cli-improvements-deliverables/exacs-bom.xlsx
Normal file
BIN
examples/output-cli-improvements-deliverables/exacs-bom.xlsx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,125 @@
|
||||
[
|
||||
{
|
||||
"id": "FF-202603-008",
|
||||
"date": "2026-03-14",
|
||||
"contributor": {
|
||||
"name": "Diego Cabrera",
|
||||
"team": "Field Architecture",
|
||||
"client": "Vector Search Customer",
|
||||
"context": "AI Vector Search engagement",
|
||||
"confidence": "validated"
|
||||
},
|
||||
"product": "ADB-S",
|
||||
"version": "23ai",
|
||||
"severity": "HIGH",
|
||||
"category": "limitation",
|
||||
"summary": "Distributed HNSW indexes not available \u2014 100M+ vector search requires partitioning workaround",
|
||||
"detail": "ADB-S AI Vector Search supports HNSW indexes but they are node-local on\nmulti-node RAC (\u226564 ECPUs). At 100M+ vectors, queries on a 2-node RAC\nmiss vectors on the other node. Results are either incomplete or require\ncross-node scan that blows P95 >200ms.\n\nWorkaround from internal DB PM team: hash-partition vector table on\nvector_id, create partition-local HNSW index. Queries hit single\npartition on single node, maintaining <50ms at 100M scale.\n\nRequires table redesign \u2014 cannot be applied to existing unpartitioned\nvector tables without data reload.\n",
|
||||
"workaround": "Hash-partition vector table by vector_id. Create HNSW index as LOCAL\n(partition-level). Ensure partition pruning in queries.\nSource: internal DB PM team contact [name].\nValidated on ADB-S 23ai with 120M vectors, P95 = 38ms on 64 ECPU.\n",
|
||||
"oracle_sr": "",
|
||||
"status": "acknowledged",
|
||||
"resolved_date": null,
|
||||
"resolution": null,
|
||||
"affects_matrix": "AI Vector Search (HNSW)",
|
||||
"tags": [
|
||||
"vector-search",
|
||||
"hnsw",
|
||||
"distributed",
|
||||
"rac",
|
||||
"partitioning",
|
||||
"100m",
|
||||
"latency",
|
||||
"ai-vector-search"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "FF-202603-002",
|
||||
"date": "2026-03-08",
|
||||
"contributor": {
|
||||
"name": "Diego Cabrera",
|
||||
"team": "Field Architecture",
|
||||
"client": "Strategic Migration Customer",
|
||||
"context": "Production migration",
|
||||
"confidence": "validated"
|
||||
},
|
||||
"product": "ADB-S Dedicated Elastic Pool (DEP)",
|
||||
"version": "23ai",
|
||||
"severity": "HIGH",
|
||||
"category": "limitation",
|
||||
"summary": "ADG must be disabled before joining Dedicated Elastic Pool",
|
||||
"detail": "When attempting to add an ADB-S instance with active Autonomous Data Guard\nto a Dedicated Elastic Pool, the operation fails. ADG must be explicitly\ndisabled before the instance can join the DEP. This is a known issue\nacknowledged by Oracle but not prominently documented.\n\nImpact: requires a brief HA gap during DEP onboarding. Must coordinate\nwith the customer's change window.\n",
|
||||
"workaround": "Disable ADG \u2192 join DEP \u2192 re-enable ADG. Plan for ~15 min HA gap.",
|
||||
"oracle_sr": "",
|
||||
"status": "acknowledged",
|
||||
"resolved_date": null,
|
||||
"resolution": null,
|
||||
"affects_matrix": "Elastic Pool Membership",
|
||||
"tags": [
|
||||
"dep",
|
||||
"adg",
|
||||
"elastic-pool",
|
||||
"ha",
|
||||
"limitation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "FF-202603-004",
|
||||
"date": "2026-03-01",
|
||||
"contributor": {
|
||||
"name": "Diego Cabrera",
|
||||
"team": "Field Architecture",
|
||||
"client": "Strategic Migration Customer",
|
||||
"context": "Production migration",
|
||||
"confidence": "validated"
|
||||
},
|
||||
"product": "ADB-S",
|
||||
"version": "23ai",
|
||||
"severity": "MEDIUM",
|
||||
"category": "gotcha",
|
||||
"summary": "DEP provisioning takes days to weeks depending on capacity",
|
||||
"detail": "Dedicated Elastic Pool provisioning is NOT instant like ADB-S Serverless.\nIt requires physical Exadata infrastructure allocation. Lead time varies\nfrom 3 days (if capacity available in region) to 2-3 weeks (if capacity\nneeds to be provisioned).\n\nBilling starts only at AVAILABLE state, not at request time.\nCo-location of existing ADB-S instances happens at the next maintenance\nwindow after joining, not immediately.\n",
|
||||
"workaround": "Request DEP early in the project timeline. Don't make it a critical-path dependency in week 1.",
|
||||
"oracle_sr": "",
|
||||
"status": "acknowledged",
|
||||
"resolved_date": null,
|
||||
"resolution": null,
|
||||
"affects_matrix": "Elastic Pool Membership",
|
||||
"tags": [
|
||||
"dep",
|
||||
"provisioning",
|
||||
"lead-time",
|
||||
"capacity",
|
||||
"planning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "FF-202603-007",
|
||||
"date": "2026-02-10",
|
||||
"contributor": {
|
||||
"name": "Diego Cabrera",
|
||||
"team": "Field Architecture",
|
||||
"client": "Pepe SRL",
|
||||
"context": "Discovery engagement",
|
||||
"confidence": "validated"
|
||||
},
|
||||
"product": "ADB-S",
|
||||
"version": "23ai",
|
||||
"severity": "INFO",
|
||||
"category": "gotcha",
|
||||
"summary": "ADB-S Serverless RAC node split threshold at 64 ECPUs",
|
||||
"detail": "ADB-S Serverless runs on 1 RAC node at \u226424 ECPUs and splits to 2 nodes\nat 64 ECPUs (16 cpu_count each). The gv$instance view only shows nodes\nwhere the PDB is open.\n\nThis affects connection pooling behavior and session distribution.\nApplications should use UCP or JDBC connection pool with FAN events\nto handle the multi-node scenario properly.\n",
|
||||
"workaround": "Ensure connection pool configuration handles multi-node. Use UCP with FAN.",
|
||||
"oracle_sr": "",
|
||||
"status": "acknowledged",
|
||||
"resolved_date": null,
|
||||
"resolution": null,
|
||||
"affects_matrix": null,
|
||||
"tags": [
|
||||
"adb-s",
|
||||
"rac",
|
||||
"ecpu",
|
||||
"node-split",
|
||||
"connection-pooling"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"total": 8,
|
||||
"by_severity": {
|
||||
"HIGH": 2,
|
||||
"MEDIUM": 4,
|
||||
"LOW": 1,
|
||||
"INFO": 1
|
||||
},
|
||||
"by_product": {
|
||||
"ADB-S": 4,
|
||||
"OCI CLI": 1,
|
||||
"ADB-S Dedicated Elastic Pool (DEP)": 2,
|
||||
"OCI DMS": 1
|
||||
},
|
||||
"by_status": {
|
||||
"acknowledged": 5,
|
||||
"open": 2,
|
||||
"monitoring": 1
|
||||
},
|
||||
"by_category": {
|
||||
"limitation": 3,
|
||||
"bug": 1,
|
||||
"undocumented": 1,
|
||||
"gotcha": 3
|
||||
}
|
||||
}
|
||||
206
examples/output-cli-improvements-deliverables/kb-search-adb.json
Normal file
206
examples/output-cli-improvements-deliverables/kb-search-adb.json
Normal file
@@ -0,0 +1,206 @@
|
||||
[
|
||||
{
|
||||
"file": "kb/architecture-center/catalog.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 25,
|
||||
"text": "- title: \"Deploy Oracle Autonomous Database on Oracle Database@Azure\""
|
||||
},
|
||||
{
|
||||
"line": 267,
|
||||
"text": "- title: \"Deploy Oracle Autonomous Database on Oracle Database@Google Cloud\""
|
||||
},
|
||||
{
|
||||
"line": 427,
|
||||
"text": "- title: \"Migrate on-premises Oracle Database to Autonomous Database\""
|
||||
},
|
||||
{
|
||||
"line": 463,
|
||||
"text": "- title: \"Migrate a PeopleSoft database to Oracle Autonomous Database\""
|
||||
},
|
||||
{
|
||||
"line": 623,
|
||||
"text": "- title: \"Move Oracle Forms applications to Oracle APEX on an Oracle Autonomous "
|
||||
},
|
||||
{
|
||||
"line": 635,
|
||||
"text": "- title: \"Stream Kafka topics to Oracle Autonomous Database using Oracle Integra"
|
||||
},
|
||||
{
|
||||
"line": 795,
|
||||
"text": "- title: \"Implement Oracle Data Safe for Exadata and Autonomous Databases\""
|
||||
},
|
||||
{
|
||||
"line": 1140,
|
||||
"text": "- title: \"Deploy a microservices-based application in Kubernetes connected to an"
|
||||
},
|
||||
{
|
||||
"line": 1226,
|
||||
"text": "- title: \"Deploy JD Edwards EnterpriseOne with Oracle Autonomous Database on Ded"
|
||||
},
|
||||
{
|
||||
"line": 1262,
|
||||
"text": "- title: \"Run PeopleSoft ERP and Autonomous Database in an HA multicloud deploym"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/competitive/aws-mapping.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 32,
|
||||
"text": "- \"Autonomous Database \u2014 no equivalent in AWS\""
|
||||
},
|
||||
{
|
||||
"line": 81,
|
||||
"text": "- \"Data Safe included free for Autonomous Database\""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/competitive/common-objections.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 12,
|
||||
"text": "- Only cloud with Autonomous Database"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/patterns/database-ha-adb-s.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 2,
|
||||
"text": "# Composable architecture block for Autonomous Database Serverless HA"
|
||||
},
|
||||
{
|
||||
"line": 10,
|
||||
"text": "Autonomous Database Serverless (ADB-S) provides built-in high availability throu"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/pricing/oci-sku-catalog.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 462,
|
||||
"text": "display_name: Oracle Cloud Infrastructure - Autonomous Database & Exadata"
|
||||
},
|
||||
{
|
||||
"line": 465,
|
||||
"text": "product: Oracle Autonomous Database (ATP or ADW) - ECPU (2 ECPU minimum)"
|
||||
},
|
||||
{
|
||||
"line": 471,
|
||||
"text": "product: Oracle Autonomous Database (ATP or ADW) - BYOL ECPU (2 ECPU minimum)"
|
||||
},
|
||||
{
|
||||
"line": 477,
|
||||
"text": "product: Oracle Autonomous Database Storage for Transaction Processing (ATP), us"
|
||||
},
|
||||
{
|
||||
"line": 483,
|
||||
"text": "product: Oracle Autonomous Database Storage for Data Warehouse (ADW), using ECPU"
|
||||
},
|
||||
{
|
||||
"line": 489,
|
||||
"text": "product: Oracle Autonomous Database Backup Storage (ATP or ADW), using ECPU"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/services/adb-dedicated.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 3,
|
||||
"text": "service: Autonomous Database Dedicated (ADB-D)"
|
||||
},
|
||||
{
|
||||
"line": 8,
|
||||
"text": "what: Autonomous Database on dedicated Exadata infrastructure. Provides isolatio"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/services/adb-elastic-pool.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 3,
|
||||
"text": "service: Autonomous Database Serverless Elastic Pool"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/services/adb-serverless.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 1,
|
||||
"text": "# OCI Service: Autonomous Database Serverless (ADB-S)"
|
||||
},
|
||||
{
|
||||
"line": 5,
|
||||
"text": "name: \"Autonomous Database Serverless (ADB-S)\""
|
||||
},
|
||||
{
|
||||
"line": 38,
|
||||
"text": "name: \"Autonomous Database Serverless (ADB-S)\""
|
||||
},
|
||||
{
|
||||
"line": 47,
|
||||
"text": "name: \"Autonomous Database on Dedicated Exadata (ADB-D)\""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/services/database-at-aws.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 32,
|
||||
"text": "notes: \"Autonomous Database on dedicated Exadata \u2014 NOT serverless\""
|
||||
},
|
||||
{
|
||||
"line": 37,
|
||||
"text": "- name: \"Autonomous Database Serverless (ADB-S)\""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/services/exadata-cloud.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 20,
|
||||
"text": "- \"Small workloads under 16 OCPUs \u2014 use Autonomous Database Serverless (ADB-S) o"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/services/oci-networking-core.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 46,
|
||||
"text": "description: \"Private pathway from a VCN to supported OCI services (e.g., Object"
|
||||
},
|
||||
{
|
||||
"line": 84,
|
||||
"text": "description: \"Resources in private subnets cannot reach OCI services (Object Sto"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "kb/well-architected/security-compliance.yaml",
|
||||
"matches": [
|
||||
{
|
||||
"line": 148,
|
||||
"text": "description: \"Private endpoints for Autonomous Database\""
|
||||
},
|
||||
{
|
||||
"line": 150,
|
||||
"text": "pass_if: \"Autonomous Database configured with private endpoints\""
|
||||
},
|
||||
{
|
||||
"line": 151,
|
||||
"text": "gap_if: \"Autonomous Database using public endpoints\""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,50 @@
|
||||
[
|
||||
{
|
||||
"feature": "Auto Indexing",
|
||||
"category": "auto_management",
|
||||
"compatibility": [
|
||||
{
|
||||
"deployment": "ADB-S Serverless",
|
||||
"version": "23ai",
|
||||
"status": "GA_CAVEAT",
|
||||
"notes": "Creates indexes HIDDEN by default. Instantly reversible. DML costing prevents over-indexing. Deduplication with manually created indexes."
|
||||
},
|
||||
{
|
||||
"deployment": "ADB-S Serverless",
|
||||
"version": "26ai",
|
||||
"status": "GA",
|
||||
"notes": "Improved in 26ai \u2014 better cost model, fewer false positives."
|
||||
},
|
||||
{
|
||||
"deployment": "ADB-S Elastic Pool",
|
||||
"version": "23ai",
|
||||
"status": "GA_CAVEAT",
|
||||
"notes": "Same as ADB-S Serverless."
|
||||
},
|
||||
{
|
||||
"deployment": "ADB Dedicated Elastic Pool (DEP)",
|
||||
"version": "23ai",
|
||||
"status": "GA_CAVEAT",
|
||||
"notes": "Available but less tested in DEP."
|
||||
},
|
||||
{
|
||||
"deployment": "ADB on Dedicated Exadata",
|
||||
"version": "23ai",
|
||||
"status": "GA",
|
||||
"notes": "Fully supported."
|
||||
},
|
||||
{
|
||||
"deployment": "Exadata Cloud Service",
|
||||
"version": "23ai",
|
||||
"status": "NOT_AVAIL",
|
||||
"notes": "Not an ADB feature. Use manual indexing."
|
||||
},
|
||||
{
|
||||
"deployment": "Base DB Service (EE)",
|
||||
"version": "23ai",
|
||||
"status": "NOT_AVAIL",
|
||||
"notes": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,86 @@
|
||||
[
|
||||
{
|
||||
"feature": "AI Vector Search (HNSW)",
|
||||
"category": "developer",
|
||||
"compatibility": [
|
||||
{
|
||||
"deployment": "ADB-S Serverless",
|
||||
"version": "23ai",
|
||||
"status": "GA_CAVEAT",
|
||||
"notes": "HNSW indexes are node-local on multi-node RAC. Works well up to\n~50M vectors on single node (\u226424 ECPUs). At 100M+ on multi-node\n(\u226564 ECPUs), requires hash-partitioned vector table with LOCAL\nHNSW index for <50ms P95. See FF-202603-008.\n"
|
||||
},
|
||||
{
|
||||
"deployment": "ADB-S Serverless",
|
||||
"version": "26ai",
|
||||
"status": "UNTESTED",
|
||||
"notes": "Check if distributed HNSW is added in 26ai. Expected to remain node-local."
|
||||
},
|
||||
{
|
||||
"deployment": "ADB-S Elastic Pool",
|
||||
"version": "23ai",
|
||||
"status": "GA_CAVEAT",
|
||||
"notes": "Same node-local limitation as ADB-S Serverless."
|
||||
},
|
||||
{
|
||||
"deployment": "ADB on Dedicated Exadata",
|
||||
"version": "23ai",
|
||||
"status": "GA_CAVEAT",
|
||||
"notes": "Same limitation. Dedicated infra doesn't change HNSW locality."
|
||||
},
|
||||
{
|
||||
"deployment": "Exadata Cloud Service",
|
||||
"version": "23ai",
|
||||
"status": "GA_CAVEAT",
|
||||
"notes": "RAC with HNSW has same node-local constraint. Partitioning workaround applies."
|
||||
},
|
||||
{
|
||||
"deployment": "Base DB Service (EE)",
|
||||
"version": "23ai",
|
||||
"status": "NOT_AVAIL",
|
||||
"notes": "AI Vector Search requires 23ai. Available in EE but HNSW performance limited without Exadata storage."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"feature": "AI Vector Search (IVF)",
|
||||
"category": "developer",
|
||||
"compatibility": [
|
||||
{
|
||||
"deployment": "ADB-S Serverless",
|
||||
"version": "23ai",
|
||||
"status": "GA",
|
||||
"notes": "IVF (Inverted File) indexes ARE distributed across RAC nodes.\nWorks at 100M+ scale without partitioning. However, IVF has\nlower recall than HNSW at same latency budget. Trade-off:\nIVF for scale without redesign, HNSW+partitioning for best recall.\n"
|
||||
},
|
||||
{
|
||||
"deployment": "ADB-S Serverless",
|
||||
"version": "26ai",
|
||||
"status": "UNTESTED",
|
||||
"notes": ""
|
||||
},
|
||||
{
|
||||
"deployment": "ADB-S Elastic Pool",
|
||||
"version": "23ai",
|
||||
"status": "GA",
|
||||
"notes": "Same as ADB-S Serverless."
|
||||
},
|
||||
{
|
||||
"deployment": "ADB on Dedicated Exadata",
|
||||
"version": "23ai",
|
||||
"status": "GA",
|
||||
"notes": ""
|
||||
},
|
||||
{
|
||||
"deployment": "Exadata Cloud Service",
|
||||
"version": "23ai",
|
||||
"status": "GA",
|
||||
"notes": "IVF distributed across RAC nodes. Exadata storage accelerates scans."
|
||||
},
|
||||
{
|
||||
"deployment": "Base DB Service (EE)",
|
||||
"version": "23ai",
|
||||
"status": "NOT_AVAIL",
|
||||
"notes": "AI Vector Search requires 23ai. Available in EE but performance limited without Exadata."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"query": "ADB-S vs AWS Aurora / Azure SQL",
|
||||
"aws_database_mappings": [],
|
||||
"azure_database_mappings": [
|
||||
{
|
||||
"oci": "ADB-S",
|
||||
"azure": "Azure SQL Managed Instance / Azure Database for PostgreSQL",
|
||||
"oci_advantage": "ADB-S runs actual Oracle Database. Azure SQL MI is SQL Server only.\nNo native Oracle database service on Azure.\nOracle on Azure VMs loses Exadata performance and autonomous operations.\n",
|
||||
"azure_advantage": "Native SQL Server support if migrating from SQL Server."
|
||||
},
|
||||
{
|
||||
"oci": "ExaCS",
|
||||
"azure": "Oracle Database@Azure (ExaCS in Azure datacenters)",
|
||||
"notes": "Oracle Database@Azure is ExaCS running in Azure datacenters with\ndirect connectivity to Azure services. Available in select regions.\nThis is a partnership offering, not a competitive comparison.\n"
|
||||
}
|
||||
],
|
||||
"common_objections": [
|
||||
{
|
||||
"id": "OBJ-001",
|
||||
"category": "market",
|
||||
"objection": "OCI is a niche cloud \u2014 AWS/Azure are the leaders",
|
||||
"response": "OCI is the #4 cloud globally and growing fastest in database PaaS.\nFor Oracle database workloads specifically, OCI is the leader:\n- Only cloud with Exadata hardware\n- Only cloud with Autonomous Database\n- Best Oracle license portability\nThe question isn't \"best cloud overall\" but \"best cloud for this workload.\"\n",
|
||||
"evidence": "Gartner, IDC reports on cloud database market"
|
||||
},
|
||||
{
|
||||
"id": "OBJ-002",
|
||||
"category": "risk",
|
||||
"objection": "What if Oracle EOLs or changes OCI pricing?",
|
||||
"response": "OCI pricing has only decreased since launch. Oracle's cloud investment\nis $50B+ in CapEx. OCI is Oracle's strategic platform \u2014 not a side project.\nContractual pricing protection exists via Annual Flex and Universal Credits.\n",
|
||||
"mitigation": "Use annual flex contracts with pricing guarantees"
|
||||
},
|
||||
{
|
||||
"id": "OBJ-003",
|
||||
"category": "skills",
|
||||
"objection": "Our team has no OCI experience",
|
||||
"response": "ADB-S reduces DBA workload by 80% (no patching, tuning, scaling).\nOCI console follows familiar cloud patterns. Terraform provider is mature.\nOracle provides free training and certification. Typical ramp-up is 2-4 weeks.\n",
|
||||
"mitigation": "Include training budget in migration plan"
|
||||
},
|
||||
{
|
||||
"id": "OBJ-004",
|
||||
"category": "features",
|
||||
"objection": "OCI doesn't have as many services as AWS",
|
||||
"response": "True for breadth (AWS has 200+ services). For database and enterprise\nworkloads, OCI feature parity is strong. Key services are GA:\n- Compute, networking, storage, Kubernetes, serverless\n- Monitoring, logging, IAM, security\n- Queue, Streaming, API Gateway\nWhat matters is whether OCI has what *you* need, not a raw count.\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
[
|
||||
{
|
||||
"id": "FF-202604-001",
|
||||
"date": "2026-04-12",
|
||||
"contributor": {
|
||||
"name": "Test SA",
|
||||
"team": "Validation",
|
||||
"date": "2026-04-12",
|
||||
"confidence": "observed",
|
||||
"client": "Test Client",
|
||||
"context": "CLI validation"
|
||||
},
|
||||
"reported_by": "Test SA",
|
||||
"product": "OCI Queue",
|
||||
"version": "GA",
|
||||
"severity": "LOW",
|
||||
"category": "gotcha",
|
||||
"summary": "Queue message visibility timeout resets on failed processing \u2014 must handle idempotently",
|
||||
"detail": "When a consumer fails to process a message within the visibility timeout, the message becomes visible again. If the consumer partially processed it, you get duplicate processing.",
|
||||
"workaround": "Implement idempotent consumers. Use message deduplication ID.",
|
||||
"oracle_sr": "",
|
||||
"status": "open",
|
||||
"resolved_date": null,
|
||||
"resolution": null,
|
||||
"affects_matrix": null,
|
||||
"tags": [
|
||||
"queue",
|
||||
"messaging",
|
||||
"idempotency"
|
||||
],
|
||||
"confirmations": []
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,5 @@
|
||||
WARNING: Unknown tag 'queue'. Not in taxonomy.
|
||||
WARNING: Unknown tag 'messaging'. Did you mean 'sizing'?
|
||||
WARNING: Unknown tag 'idempotency'. Did you mean 'latency'?
|
||||
|
||||
Added: FF-202604-001 [LOW] Queue message visibility timeout resets on failed processing — must handle idempotently
|
||||
@@ -0,0 +1,174 @@
|
||||
well_architected_scorecard:
|
||||
overall_status: GAPS_IDENTIFIED
|
||||
generated_date: '2026-04-12T21:26:00.300204'
|
||||
architecture_name: examples/meli-kvs-wa-architecture.yaml
|
||||
customer: Unknown
|
||||
summary:
|
||||
total_checks: 23
|
||||
total_passed: 18
|
||||
total_gaps: 5
|
||||
high_severity_gaps: 2
|
||||
medium_severity_gaps: 1
|
||||
low_severity_gaps: 2
|
||||
pillars:
|
||||
security_compliance:
|
||||
status: GAPS_IDENTIFIED
|
||||
checks_passed: 12
|
||||
checks_total: 15
|
||||
categories:
|
||||
identity_access:
|
||||
passed: 3
|
||||
total: 4
|
||||
gaps:
|
||||
- check_id: SEC-IAM-003
|
||||
area: Identity & Access
|
||||
finding: no mention of admin account restrictions
|
||||
severity: HIGH
|
||||
recommendation: separate admin groups defined for operations
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
resource_isolation:
|
||||
passed: 3
|
||||
total: 3
|
||||
gaps: []
|
||||
database_security:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
data_protection:
|
||||
passed: 1
|
||||
total: 2
|
||||
gaps:
|
||||
- check_id: SEC-DAT-001
|
||||
area: Data Protection
|
||||
finding: any storage service without encryption at rest
|
||||
severity: HIGH
|
||||
recommendation: encryption at rest specified for all storage services
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
network_security:
|
||||
passed: 3
|
||||
total: 3
|
||||
gaps: []
|
||||
monitoring_audit:
|
||||
passed: 2
|
||||
total: 3
|
||||
gaps:
|
||||
- check_id: SEC-MON-003
|
||||
area: Monitoring & Audit
|
||||
finding: no VCN Flow Logs configured
|
||||
severity: MEDIUM
|
||||
recommendation: VCN Flow Logs enabled for critical subnets
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
reliability_resilience:
|
||||
status: PASS_WITH_RECOMMENDATIONS
|
||||
checks_passed: 0
|
||||
checks_total: 1
|
||||
categories:
|
||||
scalability:
|
||||
passed: 0
|
||||
total: 1
|
||||
gaps:
|
||||
- check_id: REL-SCL-002
|
||||
area: Scalability
|
||||
finding: no service limit review planned
|
||||
severity: LOW
|
||||
recommendation: service limit review mentioned in deployment plan
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/reliable-and-resilient-cloud-topology-practices1.html
|
||||
fault_tolerant_networking:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
data_backup:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
data_replication:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
disaster_recovery:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
performance_cost:
|
||||
status: PASS
|
||||
checks_passed: 2
|
||||
checks_total: 2
|
||||
categories:
|
||||
compute_sizing:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
storage_strategy:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
network_tuning:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
cost_management:
|
||||
passed: 2
|
||||
total: 2
|
||||
gaps: []
|
||||
operational_efficiency:
|
||||
status: PASS_WITH_RECOMMENDATIONS
|
||||
checks_passed: 4
|
||||
checks_total: 5
|
||||
categories:
|
||||
deployment_strategy:
|
||||
passed: 1
|
||||
total: 1
|
||||
gaps: []
|
||||
workload_monitoring:
|
||||
passed: 2
|
||||
total: 2
|
||||
gaps: []
|
||||
os_management:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
operations_support:
|
||||
passed: 1
|
||||
total: 2
|
||||
gaps:
|
||||
- check_id: OPS-SUP-001
|
||||
area: Operations Support
|
||||
finding: no support plan consideration
|
||||
severity: LOW
|
||||
recommendation: Oracle support plan level specified and matches criticality
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/best-practices-operating-cloud-deployments-efficiency.html
|
||||
distributed_cloud:
|
||||
status: NOT_APPLICABLE
|
||||
checks_passed: 0
|
||||
checks_total: 0
|
||||
categories: {}
|
||||
action_items:
|
||||
high_priority:
|
||||
- check_id: SEC-IAM-003
|
||||
pillar: Identity & Access
|
||||
finding: no mention of admin account restrictions
|
||||
recommendation: separate admin groups defined for operations
|
||||
- check_id: SEC-DAT-001
|
||||
pillar: Data Protection
|
||||
finding: any storage service without encryption at rest
|
||||
recommendation: encryption at rest specified for all storage services
|
||||
medium_priority:
|
||||
- check_id: SEC-MON-003
|
||||
pillar: Monitoring & Audit
|
||||
finding: no VCN Flow Logs configured
|
||||
recommendation: VCN Flow Logs enabled for critical subnets
|
||||
low_priority:
|
||||
- check_id: REL-SCL-002
|
||||
pillar: Scalability
|
||||
finding: no service limit review planned
|
||||
recommendation: service limit review mentioned in deployment plan
|
||||
- check_id: OPS-SUP-001
|
||||
pillar: Operations Support
|
||||
finding: no support plan consideration
|
||||
recommendation: Oracle support plan level specified and matches criticality
|
||||
references:
|
||||
framework: https://docs.oracle.com/en/solutions/oci-best-practices/index.html
|
||||
security: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
reliability: https://docs.oracle.com/en/solutions/oci-best-practices/reliable-and-resilient-cloud-topology-practices1.html
|
||||
operations: https://docs.oracle.com/en/solutions/oci-best-practices/best-practices-operating-cloud-deployments-efficiency.html
|
||||
distributed: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-distributed-cloud-implementation1.html
|
||||
241
examples/output-cli-improvements-deliverables/wa-scorecard.yaml
Normal file
241
examples/output-cli-improvements-deliverables/wa-scorecard.yaml
Normal file
@@ -0,0 +1,241 @@
|
||||
well_architected_scorecard:
|
||||
overall_status: GAPS_IDENTIFIED
|
||||
generated_date: '2026-04-12T22:40:14.045613'
|
||||
architecture_name: examples/meli-kvs-wa-architecture.yaml
|
||||
customer: Mercado Libre (MELI)
|
||||
summary:
|
||||
total_checks: 49
|
||||
total_passed: 39
|
||||
total_gaps: 10
|
||||
high_severity_gaps: 2
|
||||
medium_severity_gaps: 5
|
||||
low_severity_gaps: 3
|
||||
pillars:
|
||||
security_compliance:
|
||||
status: GAPS_IDENTIFIED
|
||||
checks_passed: 21
|
||||
checks_total: 26
|
||||
categories:
|
||||
identity_access:
|
||||
passed: 5
|
||||
total: 6
|
||||
gaps:
|
||||
- check_id: SEC-IAM-003
|
||||
area: Identity & Access
|
||||
finding: no mention of admin account restrictions
|
||||
severity: HIGH
|
||||
recommendation: separate admin groups defined for operations
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
resource_isolation:
|
||||
passed: 4
|
||||
total: 4
|
||||
gaps: []
|
||||
database_security:
|
||||
passed: 4
|
||||
total: 6
|
||||
gaps:
|
||||
- check_id: SEC-DB-004
|
||||
area: Database Security
|
||||
finding: Data Safe not included in architecture
|
||||
severity: MEDIUM
|
||||
recommendation: Data Safe configured for database security assessment
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
- check_id: SEC-DB-006
|
||||
area: Database Security
|
||||
finding: no mention of DELETE permission restrictions
|
||||
severity: MEDIUM
|
||||
recommendation: explicit restriction on DELETE permissions documented
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
data_protection:
|
||||
passed: 1
|
||||
total: 2
|
||||
gaps:
|
||||
- check_id: SEC-DAT-001
|
||||
area: Data Protection
|
||||
finding: any storage service without encryption at rest
|
||||
severity: HIGH
|
||||
recommendation: encryption at rest specified for all storage services
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
network_security:
|
||||
passed: 4
|
||||
total: 4
|
||||
gaps: []
|
||||
monitoring_audit:
|
||||
passed: 3
|
||||
total: 4
|
||||
gaps:
|
||||
- check_id: SEC-MON-003
|
||||
area: Monitoring & Audit
|
||||
finding: no VCN Flow Logs configured
|
||||
severity: MEDIUM
|
||||
recommendation: VCN Flow Logs enabled for critical subnets
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
reliability_resilience:
|
||||
status: PASS_WITH_RECOMMENDATIONS
|
||||
checks_passed: 6
|
||||
checks_total: 8
|
||||
categories:
|
||||
scalability:
|
||||
passed: 1
|
||||
total: 3
|
||||
gaps:
|
||||
- check_id: REL-SCL-002
|
||||
area: Scalability
|
||||
finding: no service limit review planned
|
||||
severity: LOW
|
||||
recommendation: service limit review mentioned in deployment plan
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/reliable-and-resilient-cloud-topology-practices1.html
|
||||
- check_id: REL-SCL-003
|
||||
area: Scalability
|
||||
finding: critical production workloads without capacity reservations
|
||||
severity: MEDIUM
|
||||
recommendation: capacity reservations specified for critical compute
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/reliable-and-resilient-cloud-topology-practices1.html
|
||||
fault_tolerant_networking:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
data_backup:
|
||||
passed: 3
|
||||
total: 3
|
||||
gaps: []
|
||||
data_replication:
|
||||
passed: 2
|
||||
total: 2
|
||||
gaps: []
|
||||
disaster_recovery:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
performance_cost:
|
||||
status: PASS_WITH_RECOMMENDATIONS
|
||||
checks_passed: 4
|
||||
checks_total: 5
|
||||
categories:
|
||||
compute_sizing:
|
||||
passed: 1
|
||||
total: 1
|
||||
gaps: []
|
||||
storage_strategy:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
network_tuning:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
cost_management:
|
||||
passed: 3
|
||||
total: 4
|
||||
gaps:
|
||||
- check_id: PERF-CST-006
|
||||
area: Cost Management
|
||||
finding: non-prod environments running same shapes as production 24/7
|
||||
severity: LOW
|
||||
recommendation: non-prod environments use reduced shapes or have schedules
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/index.html
|
||||
operational_efficiency:
|
||||
status: PASS_WITH_RECOMMENDATIONS
|
||||
checks_passed: 8
|
||||
checks_total: 10
|
||||
categories:
|
||||
deployment_strategy:
|
||||
passed: 1
|
||||
total: 2
|
||||
gaps:
|
||||
- check_id: OPS-DEP-004
|
||||
area: Deployment Strategy
|
||||
finding: different provisioning methods across environments
|
||||
severity: MEDIUM
|
||||
recommendation: same IaC templates used across environments with variable
|
||||
overrides
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/best-practices-operating-cloud-deployments-efficiency.html
|
||||
workload_monitoring:
|
||||
passed: 4
|
||||
total: 4
|
||||
gaps: []
|
||||
os_management:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
operations_support:
|
||||
passed: 3
|
||||
total: 4
|
||||
gaps:
|
||||
- check_id: OPS-SUP-001
|
||||
area: Operations Support
|
||||
finding: no support plan consideration
|
||||
severity: LOW
|
||||
recommendation: Oracle support plan level specified and matches criticality
|
||||
wa_reference: https://docs.oracle.com/en/solutions/oci-best-practices/best-practices-operating-cloud-deployments-efficiency.html
|
||||
distributed_cloud:
|
||||
status: PASS
|
||||
checks_passed: 0
|
||||
checks_total: 0
|
||||
categories:
|
||||
dc_deployment_strategy:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
dc_integration:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
dc_compliance:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
dc_operations:
|
||||
passed: 0
|
||||
total: 0
|
||||
gaps: []
|
||||
action_items:
|
||||
high_priority:
|
||||
- check_id: SEC-IAM-003
|
||||
pillar: Identity & Access
|
||||
finding: no mention of admin account restrictions
|
||||
recommendation: separate admin groups defined for operations
|
||||
- check_id: SEC-DAT-001
|
||||
pillar: Data Protection
|
||||
finding: any storage service without encryption at rest
|
||||
recommendation: encryption at rest specified for all storage services
|
||||
medium_priority:
|
||||
- check_id: SEC-DB-004
|
||||
pillar: Database Security
|
||||
finding: Data Safe not included in architecture
|
||||
recommendation: Data Safe configured for database security assessment
|
||||
- check_id: SEC-DB-006
|
||||
pillar: Database Security
|
||||
finding: no mention of DELETE permission restrictions
|
||||
recommendation: explicit restriction on DELETE permissions documented
|
||||
- check_id: SEC-MON-003
|
||||
pillar: Monitoring & Audit
|
||||
finding: no VCN Flow Logs configured
|
||||
recommendation: VCN Flow Logs enabled for critical subnets
|
||||
- check_id: REL-SCL-003
|
||||
pillar: Scalability
|
||||
finding: critical production workloads without capacity reservations
|
||||
recommendation: capacity reservations specified for critical compute
|
||||
- check_id: OPS-DEP-004
|
||||
pillar: Deployment Strategy
|
||||
finding: different provisioning methods across environments
|
||||
recommendation: same IaC templates used across environments with variable overrides
|
||||
low_priority:
|
||||
- check_id: REL-SCL-002
|
||||
pillar: Scalability
|
||||
finding: no service limit review planned
|
||||
recommendation: service limit review mentioned in deployment plan
|
||||
- check_id: PERF-CST-006
|
||||
pillar: Cost Management
|
||||
finding: non-prod environments running same shapes as production 24/7
|
||||
recommendation: non-prod environments use reduced shapes or have schedules
|
||||
- check_id: OPS-SUP-001
|
||||
pillar: Operations Support
|
||||
finding: no support plan consideration
|
||||
recommendation: Oracle support plan level specified and matches criticality
|
||||
references:
|
||||
framework: https://docs.oracle.com/en/solutions/oci-best-practices/index.html
|
||||
security: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html
|
||||
reliability: https://docs.oracle.com/en/solutions/oci-best-practices/reliable-and-resilient-cloud-topology-practices1.html
|
||||
operations: https://docs.oracle.com/en/solutions/oci-best-practices/best-practices-operating-cloud-deployments-efficiency.html
|
||||
distributed: https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-distributed-cloud-implementation1.html
|
||||
BIN
examples/output-demo-pharma-mx/opt01-architecture-proposal.pptx
Normal file
BIN
examples/output-demo-pharma-mx/opt01-architecture-proposal.pptx
Normal file
Binary file not shown.
269
examples/output-demo-pharma-mx/opt01-customer-proposal.pdf
Normal file
269
examples/output-demo-pharma-mx/opt01-customer-proposal.pdf
Normal file
@@ -0,0 +1,269 @@
|
||||
%PDF-1.4
|
||||
%“Œ‹ž ReportLab Generated PDF document (opensource)
|
||||
1 0 obj
|
||||
<<
|
||||
/F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 8 0 R /F5 10 0 R /F6 14 0 R
|
||||
>>
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
3 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
4 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<<
|
||||
/Contents 21 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
6 0 obj
|
||||
<<
|
||||
/Contents 22 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<<
|
||||
/Contents 23 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
8 0 obj
|
||||
<<
|
||||
/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
9 0 obj
|
||||
<<
|
||||
/Contents 24 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
10 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
11 0 obj
|
||||
<<
|
||||
/Contents 25 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
12 0 obj
|
||||
<<
|
||||
/Contents 26 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
13 0 obj
|
||||
<<
|
||||
/Contents 27 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
14 0 obj
|
||||
<<
|
||||
/BaseFont /Symbol /Name /F6 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
15 0 obj
|
||||
<<
|
||||
/Contents 28 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
16 0 obj
|
||||
<<
|
||||
/Contents 29 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
17 0 obj
|
||||
<<
|
||||
/Contents 30 0 R /MediaBox [ 0 0 612 792 ] /Parent 20 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
18 0 obj
|
||||
<<
|
||||
/PageMode /UseNone /Pages 20 0 R /Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
19 0 obj
|
||||
<<
|
||||
/Author (Carlos Mendoza) /CreationDate (D:20260413001815-03'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260413001815-03'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (OCI Architecture Proposal) /Title (PharmaCorp Mexico \204 Oracle Database Migration to OCI) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
20 0 obj
|
||||
<<
|
||||
/Count 10 /Kids [ 5 0 R 6 0 R 7 0 R 9 0 R 11 0 R 12 0 R 13 0 R 15 0 R 16 0 R 17 0 R ] /Type /Pages
|
||||
>>
|
||||
endobj
|
||||
21 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 570
|
||||
>>
|
||||
stream
|
||||
Gatn!9lJN8&;KZL(%6/,_8K]#EeJ:l.T*U0*&qmlM74Fg`5,#;(\-N'-VMuB'qu>HjKV4HH(UKZ7nS[mHdr.89>#_o_$.t%\7,g,HX)fW[tO9<E,ED#actapaeTfkD:1)r)$QEp+?8`5&n^]6dZ"R.1qa[p-J$d@1'&Osb-&O&:3I(Me-5Ck?Eidpc'6_P:gf0E[K_pG$0@l]I]O[PPVg]1EJMe5E.\V&`qO*!j*H'/F(\^iW@HN2?md%&U&9f=/.*ATcD%D6/2*=>ku"nE2^<'Ec(4/Jd!5orY,R7fk6%0Ep<HEmmtkVC_r+$D_Y<GK&_](*2n3jFV\,I_i6I&ZHc5`2`pfXj6M&j)W]TmS>d+.jNU&$5)@Pr2@L9;]=tW2!h!?W/D1*7?jmJV\5>aVpd,qeAbBT/G3LD.'U,>9<iX]%sWY3[Q.[E8:Y(Ni[LN>Q106VHIC2Ur;+\Y)FmB7)D4Pp,f?OA/&i;!0?(V#BM]D_L1l*Cp*jK+1RT<`r3PX7Tm-oq;lLg(g%5LRLHgAeDPM.8o^Xe0B6p:F_Q.EqFpJia!%ndARjp0@~>endstream
|
||||
endobj
|
||||
22 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2000
|
||||
>>
|
||||
stream
|
||||
Gau0D>Beg[%"?O+^r(JYe(L`lh08RUHe5ST(OJdsnj6!V_aY7R8kSAu5EN0]-]RL?dn\XgV$Pu]n.>Xf^rAUWr/<F^_[1]O,sWkPAjBVEKuos+1>.$,Z\$PI+po(p>`[f1s,Y%ifcGjF]c9-N!mcW14>/O0.?+"el9_U)ZM^OSbB5oc\R;t$"MP*VC*HsaC9@`]&s?+*KJFBLhD(;#,H2#0kMJ]ZpL3V%-6KY,FW'1AJ\NOU,kIEpG[:]BY)-8C*JHBqLhm_"kY5_sZo=<&]&RHMNBcRu^H+b-a)\*d1pk->.5p?S2g@ZG'npFm%gjU\TJlJp"KjF5Xb:U[?u&GUVUIsP#SmJ^"8%]5_tIG&ZGD4Ye#@tg[85;^1cY<Vj15ka*6*,e0su7<o7^1/lE"_M&GWPb/@gndOC8V_F\%#/k7Q/-HNobn2[#%b&>FnQHjprVUn/N6d+uc4PAXl'c!OlgaFYpCnIchO:b5@%,ckHR<oVQpi8ehcf7XW<D[5<Tb97k_h!Tg=naEDQ4;3&0a`jTciN!K&,C*aU""O^)=aVUfH)H2Ua[j]HWL.Z55.<TgT.++'5qL3ZKO9NMScd.L87d0UK#fGK*b81=:="MJ<J$aK+I8#nR?n\ZMg=n(.!Tb(LIQJE#"8'=gb1`8Nr@p<@hSkgFfZmD^f-APgr-#[7)P!#(nFDY@l]]0_h0cKO_N(Ms7dK>e5i?_mGRj3_X&?AhE6ULC56akH*Ma@]0FfjY(_[+;q*_>pkn"8+r)Yi0q,)/kLq%@M<\uHX\j^\,qSVT@V)C_)\&QMQ&38`NN[6,jO_RtT<(f6##7<oUtZq3igP02R_s2G/#@6H.u`ao+>.roECBt&PPB#S-/+a!,sec0o^Q@hq7=SnNnTp9aUf@sl]3ulmlO[=r-!Q?<9j/`Q.jl.A0*BKL#uAqKS$OW88<hbKUF5uQ9q+aEdJ5^TN>Nb6TdaO=uN'aZ'&[T>YJ4A@N-45ZMR&]Qdf[7QI5b*$jrl?'G\Xid?_*`;(W]^0uf?VXk3]Q:Mf2FY;&`<M1^SP.7B7M)SGo'ZT8[5Ahm0SL4YoX<f!@)-cF=i?):81'/o4?19^+fX`(6-6S5>Ze9@kK93IW92<R2$'ke/m[>@!;eKCqs_,itK[Js;c=1i!7@K:Kr^rBudX!n3bR)&pJ$B+LtTm)QcKM,@D&nY$m3=7"MkIT%\?Xl0uVk^PZpT#p/oBJoIH_'Oo_/RlV&0m5e3Q2nrUKGh%$6c!8MpeQRD(&2agb4D$F)YmFT(l9/dT".ZHQ/E6p(,$=bkK6L8S@L`04<=uXHtM,@pjF*1Q6Ra@]Jk'%5h'ETC;%\eG!>;(=]+_:+7Oc9`b_,lt/`?PXskhaKPp4r&97;Q,LLB?b^VN=0<G?0QB)G4E5gW@e.`?_a97+i&2!#m[Zt@7PfucilW"llCIlcZFrFVNk'HM)"WUBC<%bN;:t3I8:ieo-@8,-35OP_.WbY'-1l`Zq;;q;hb"XsR=ZELZM;-dn;-9G;D3i(VG2e#RIJ]72Ghsn+Vh;@5OrnP\+#+aL:\so%R>h;1#>r#(i^O9AfpRBinHbtmk:7Sq@5]KfQ+V$E]_[FEZ#"N\]?a)]=V>b9^pjBcaq%uSS;$;VI4@q-U*eHg#si(!t4k;6a\8i7^\IY.sRE7^P`HFgd]6mSdG-SHJ;Ts25Mp3c/&W4SZ>gaD'RD>PAJ@<lb9Wb[)ZVr5W^u4@_ZS/%D+COMqLaOYjsj0Q2b0Li=.]&53uZF09un%[(VmW%8H](KNC\Q@'si\"kn_X]M4b"6BB1!\C$5N1RW,52bRKL@S$+-gVo(W/@gKORo@iKUDHij.#;H0#:%PJQTH]e+"S,jj6h*<(FsYEM]V5<5K/KZQ[N61hm]6QIAn)^1,F--c(*?[DL1RCMS7`lI/H:UDqFp;RbP!UX#8V6d<:MZ6kd_%N6Q.9Q4dO\5^utOG+TbD=q-SUXo!WiR+7!LDrGF8IJLM,m[=-&rrU/\L?&~>endstream
|
||||
endobj
|
||||
23 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2270
|
||||
>>
|
||||
stream
|
||||
Gau0D8U&oI&AJ$CbY`()QJa*iY8>/^dO)5/WD*o65U7VKi>)F#U]1,8J;YhrQK)"kGn+O"1RRuMqd9U\raY[%,R8S)J=eJ30FnpL@"B!,iXMD2:-P:0PM#Q+*]W"%#T5hi2\0dY:HZ-K.3K%,&k7sM(rl8$KDA*>/gbF6-Yeo,JKK3e!1\SE8JHc/RTMNM[3bq*RUd.:Tc?PR)m441>,hqdMD$_6?bkZ>=StGLL,(<%-IG*HZn,65'nqc4)i-IPG8e),_:3&F#ec)^$[LccSNB"aC&G6>s48E4l8u]rJ/::eitPi.n/q2=A'QnPCn=X!B&L4+1_=nmJa"F((FCcfPiNN2esPBg6,<[eAGC,=HR?:2@J]f:8'U+YB3cG#<3hWU,c4TDY*CON=_0qgSUBnmB\K(Q$,PQ/""@/N\K(4ba!Uob[D$>4bJXd@.Dcus>uVUsHLABXFKVj`AoDKk3>5T!Mh@<#rCI*>-uKbT>6;5]/4,C"$_rc!1')`d28ei(SW-nZ=-ZV;aKjafXN[_=-IQ_bXe"_hI.Y&Xi[n1t6-]k^Ntert[k\O6m\JM9Y>(F+KBj72(o1Vhco'_XcE;ljC'L_:_96$*6>-g1E^gi;U[Bu?Yqd_2WNn!RMi9)nfr79!G[_.DLW07@SVtkIPpj!>=l=(,2@mFl[a#9r#f\?n'm^?-h[630Jtb)P%^#7?Aq8*Z&aGHR@2p=;l`7,Bk1KG=Sec`U"Ks9G?Pb63[8D(q9K4=h.NZTLQ=YmEhYpKU0HX1"^d9Hg0l?K6/n*X"ILEg"V'6Ut#>\suW!s<urEN.X\8e?t[>Ei*XQJ2<M)?%dS:BLqF%!E/O'ggn/X.qoQ1/dH1FD:"qsajf#]j=h26Sf>5J$r5G`aWKP68#Rj]GUG-NSoTGGY.h$#[@R#7p7;UrpEjdAsN#eoVN/n^#[.g(qE\aTb9k.sVIk$KV7j#o=G)C`io@N]p]#/)7>N]H-if9"!1umS?b*Xc&D[#*MGThVp^(50PWm1BgXnq9(eRM.M%de`glE':gprS(4`&3sSV.C0OOkJkojV6%$Lh`Q".9ZJWX05;4PXW[uLEr<nQg8H3/c/Rlg:MSKZs5#KH4Z1T:%L+g(Q)Y"ic)?'i,.$.?aCQu1KP:4<*T@\dJI)*PAY,qa6"!QCB"[\`@PmFa3USGuc:h[l+N9r6JV^P"/O\Rt2"t:_3a-21fo6>d.D'AN_Z5-.A2juhCqTBdL>Mk\22;.OFbj&/2Tfk@kabrP,W\6U7*ouHW,Z8-f%rrUR3$PgtB#tm:]$$9Yc\ir7SiT=Gd+HkZaBTs6&ef<qUH%i7C$"(I/G,D061@VGUS-<.HgPuGrP-=6J=G7Niq9d2*Ye*_eTrn`fg5(Ncjqsl3j9^FR`-=S3W=s%S!I@9:Ee>IFUkYY%^@F2??WTXlaB/Jr]mp='XK?t&_Ps_(!Os0Np!iIYaOi+s/>Al:E[NkB4ekBIE8k"OHoTG98-+/C-Kq]XiS)Z-4;E/`,F:b+K76H:&0hR=$+oX?l-Q)Q/W**RpMYg0Yf3,5l4t93#.ji1l1%0RIMRU@sbV6@*eiQ92XW'2nNsFHW&H*91=%MUeWc@WC&Y2,l"&&67BWcOE9sI,#27s@h1YlkZ:Ys"(HuH8aQ%QkOF/EqE.A"b\.WG@AC<Gm=p5G[J54)5*ZF[D=!gSgkc<+f+GIU;gdupqT9j9qR(UQ0ZTU1#>tk=$jPrG^83--/ZT5j[kf-1rHM\-EijSoO\,##():bj4#Wj3WA,_Z(3Lf.Y%3BW1]Ttr'jUi^GIPEd=^e=paLV"I`PigB#V!Dhgp;HN.%6@X(r:T7g@!Ta4*@NO>3]UkGTsB<m647cmotVnG8J5aSaBR2ok*WF.$3cM8lZZ!5n>F#j#dg(B,&\Q5PA"/??D9K)-(8ea$%k)TA\Q'&nh4"7Uho]?"Vk#Y,J+Uo'&O3nt4V$*fek3Y3]99OSC)!-$V@cW)%?`!u0s]0HJ3DH#k8O)C@3=+YAnhjiZD]Z,@WW&OIdp/Zn-VSK#6ID3U^R_TC@U-oFQ\qY3(iSk'17`SaPuN`%Up/UP3-$u[HLZ,b^P_6e$V`s8-"ipln]'9Anj\lUbAk(U7>=NmMQ[-ZTY"s,c8\C4O(`TuhM?GtX(#B/t-p#4I!m<FIH"H5)bC8]iSnb<QCrr.Ye<]3W+[q(NULiml'Ph+X''mHm[q>.LpkP"c-h(%s<AsM6LeUB.jlpYgF/E0=3k',g6-]RY:)@N"CcA)(#ZgdAnN:0R#jBp)$k@4~>endstream
|
||||
endobj
|
||||
24 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1936
|
||||
>>
|
||||
stream
|
||||
Gau0D?!#c?&:N_CbgW/j?!L$g^Wu7?8q>@-7nU((+*^X&-#p2l<48Luq]/7J#`q"tlTI8H[URM:RCOPJ6,:GM1#GP4n6lao:C%L=iu&Ej0GpG"nbD%_JJ1MU(K59daF&RUrC#W@oROgW5lj0%cjq6(hiGue#,?g9\O]q_SR?$Q@@g8)"qDk'%"*$@'(J=cF$5)U+;ofD;@^D!JubC`8[X3ZnM<o#)]4'[nQTjJEt7`20\Db:,`>ed'h+DYCh&>9]5cmUK%MAhJC-dI7RuM69fS_&@cK2Ps"to;H]CT6d)_&[:jamGm>-E.-]U)kmOqS/!Hi+\1#Xo(VO8%+&@rcYP2kb\.2PZ1W'U=[`'Yaf^-aGB#9gDbF$T6S"pc,n+4L#eqKG'Hpa",4l2gm76!Eib&dkd1,4C22G_4rnOs"'UdI\RNWJ*TkR?o/a4M9r9^U+f=XcX3Z*5ZN*8DLnP%98j<o`/\,T51,g`Kc,R[).'O._QKLi"_$rR]@l:&k6-COOonBi++[S#-!c>-nE7e;8N_TUf.:MM.mi7R>ge;[MQ5gi:t1qGVO%jeJn1:0LbjP?K-&QQ<BZLV<M>@pkk,r3mB.A.@J),-b&bHUI;"k+ptJN#rfOpRV@OWMI/<,L(GrDBAc?*Q=r5k2fG5;b-4lW2TLsI^)o6N`jAU8`COJS]3$b!.tqfjQ,411fK+f/+sgXj(7Qal_al_M+%1[8=#4^d3cgq,N^^gGD%4b0fISn%^!Njc6Fan=3TIC:T!%uI"5*)<;ARpR4&\C8i'bt.Cl_#j-tF[f]:&,u&MBKTYhbCRRo+oG9j_IRptVf`-8`7\/\1W3L'tUsBe+]]-@<Xh=(tOpQDqG5XpNoc)9.-O1\%rb55rZb7dt:g;nk,J]P^;I=#*:5ah!u9<4A(8&6R#"[jPDNDER`V@h!Cfg:\s9rQUjNolM[iWNA!0F8MumM8u/UhG_9dS24*\h-%-Cm)7Eq[KOs2PL[rf$97gl[nAe6ht9G<ZJ"_dbIs?l(J+e*8h(NGHV2rpNp)fZq>YKt'E3F["^Pm:hqW%IGb_ZEURq+>qddWnI)Z*[@U@^>$6R;jo,`7c7[l-dN"P&a)Aq.>DqASaQTE]e]j(Me3WeoOJ$=-t+$RFR.6d?1MA/5ADO5ph/T=3(WKl#A=u'V;09Y-j6dI;1SI/O9"T.<3P8IH/`=l\tjkFJ%PNSNMJp@8u%n9XXChp6J4#)F8YED=Xbl>VdBj(NeS%3eq`KI"39k=?G#1FL0B$9=faF(G(>)]aga2e\aaFHK2#Ipf,^qne8?bb$_,\jtLVZqL*khV=SKWCk(39sr(K>C5TKeb)M=%K\0mpDReF^2Uh-$V&-q@2X!DVhb:oV/Q_Qm5fa!ITco4Q=HP\]PLp#tnOI7<+YD=laFO=JH5Z/l>oEoMOrSW)JC!dmkXSALiFS.4hf/$0CthQZt\B_/BkI))"Vo\PR?E,S0%UKEFjn'/?Uh42jAJF[G1_;;FlfgZlrK2#*.)jKMn3>6/)k/hN\#f;EdDcqlL>Ok6GR9Ng)"d4"2kf[p+Z+iikM!;Br3NjYu#K"+GZQ_RJUFXCq2fIWH/@%0A#C=Z/!$kNB?bsQp5-)NuQ1H=?)FX2l3lQ?;.OKbf6)4jaSU(XI;'o8JT=X%cgYu03]D2khB.TmpfI4TA"9uhKtN2p'T*gUD&iYAUIAS$.g([3Ta4LcB'S..tJd64:Em^977,kAQ8Gl3@-(V!*-U.dG=nMpYkkW=#""ZPV./&d]G^ni[?HI<k96.@?o*fn.I2TlOHXWY9T',Flp,"5@i)Pbh%kqlpFP.o=&btcb1Sj@reV;B1p^?mAbUZ1VIc+2A-##A\%".3Zj^3'O83gDXVec-anR5*Oi:Q`q#gp#&MSf.d'WYh:kj#\JhhSH%i&4^1uK#pmCBQ]mQ<B\Y@*;g1A-GD_~>endstream
|
||||
endobj
|
||||
25 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2349
|
||||
>>
|
||||
stream
|
||||
Gau0F=``=U&:XAWfS="WD%q^)n%QoPijKN@Nhn)iN*ftMZC18[GW9SjI<P^TU25[L*-=<"@$'%>p:sui!u$0Or'*jU:1j"`4Ti]4[K'nY2U"A#A9RV4aRFT+$9/mXZQ4cBoG`SOo-4b&O"tZjn/N6BE#`5f&ss^tjF![;(iD^bYUtV82Ae>^T'LoXPaLJsECU79"%a,iLJg+G\eddb:@hp$(XZ_4k!-]K/'NGhEr@f<0g)phmPN6*nN=so=<tR)7UQG7M$O0H"YNF-b6:II33>.U&Q/,?jc9be"3[pY%GWmi-'Yot^tBn<B1ChR?61bX3!!o;[s-aD)Q#[VRc'Te.87ig9L1?DOR8`p$pRG[#p^1[Rbk`eO>=qrV+AXjlle"P/4IOoWMi4Jhpp*mh^=rMT]8`6^u4qfLWSVf'YV`-:K$L>4k.1*=Y!'+maqOieIG7uB.H"k#gm))"U?XT(@`1Q/:L(C\u+YSD&q5P/c:jrReL)l]l*B&F`_g);/.7;"OcmekP(O/^e@ZMl5s/CdV:YmUX3*'<qQX!iUI^]T>poNg"f]G4RgbW?:=Uu1/C:QkLinq[RJU&-+$J>Z@^\(#b1BYCBc\)#1l)`_jR8bXO0/E.e7j*p*Di83W;uJ79#*f^\MT![If!:4GqT:r5mRpI&]V470QqSn8GhqgdBoBn`JYb1+IV^-R[@T9ZL3Z3;YI]Z8'$6QtOf/%Rh,W!<Ek4%SrTH$;jh-C9fJ##70EASp_FmCD.J*\>QLYG7NrSn@(jECRA-HS)=2I2oekE,o_fqFgBa^oRId#%R0(r:b)+L*CQ+*oJhZO2)pCNkTA$u^uDAMhEHuB>N<:!Nb9a'$D/u9m>D61UTR6-rF(g):dns'7j^4b!cBpi'MC1A^2DU9PgNACkQ@C?_`Yo/C,#=g8OQ'VE&QDJGPq2XO)e#2&uhrABLP?]>Gfc=\[H#AhGI(@T+"nD_.jL=&%.1NFq;ilp2H`!!gEP:BWBU?.M"M,OWHC'eMA-p7>4.3g*`Ma(Mf&sW8d+,^?+]6]%/E@\+uTJdM2[1_-\gq30!qY/g?*#Et56RObqmT!&IWI,2(g,cN=U3:%3e0c:SW_<lM8m`>R]aI>Hei!u.888=ed@qGtX*<'i(7n=FMrGqYJ9Q*-*J8L%Q!,tj1C:h(o/k+7naaRT[;#*@3THEi:DR-J\&mu'5jYt$'$Y<G8GR8t%m&+=,O'r#$$&3Yb>4ib&TiJ)JXjXFdm.92t5Lf#Xac_H7]W33b[2/UY3F>hQ+-`F>X(TTG<@9dS<_gH[CNeSY.dBI78c&VP'A3[#&3p_"gm.Fe$T>&$h5K7'[H_ehI)bN]c=pBHgm>F*-mLq&fYJu'_&(P!pB*:HAj5dDe%g+pF$cA5-+s%itC/n7Tgn(eN^GY:KN36M4SRW3Od"aA,e'`l]@fFG'c!C%n`69=n!FCbVp$gt.J?Y+c*hi^7OG0)Z05*i*D3<9V<S.8#kL8**gG4lX(u"uUHFN"D1`-$m?4XC@/?acZq!>YqRs&#heC$jGcVE=l0jMNTo]crBiYN.4g,]mHV6.=4W[AQ>2&X#cXJM,*`CKVC2V,d(m:Bcj)Q/a'er3M)Bm`GL)PGrf*0`>?eMQXX?Bc&k!C-'rKUheh6_<FC(53K\H%*BD,.LsKeSd4M(=o[jOm2;@F'q0`7iS4:_8,"Acj(Q6I$[`G+&KGIKAYeTDt"X>k-"PN$aWo]KM$0PHF4mjFaETO(/kJ3-%AGb@$d3g3ZFS[\6s+"oBfWMk\65GDiPiZFohfC?LA53=qL%V/<0LsD<f`)iVI$]Yn=R#2\]uU0*Bqk3r".A^INGho"-tul/)JAbqWC2W(h0PIQ\G#DS99/oWCo;C:5K;;tqEi65<u:o`dfIO"3bc>+Qkl^[9GME-=5\D_Ei6>G/kJ[PK[_>=/cKDXEY1Fg.V:$qg%$Q!jJR2YH.ee<B>Up#I'iT)FkS)gemIglll5:Y)"_Z>T<V]%Nu":Gf]GMSJ%dqPucgh/cYEG.VCjp36hLh.$pNe/22f<YBA@O[I1rX'2Zt=V`@md^*Q-\'J1(Xr@UKb[$3ZpA1fj`34R(;1E^Ro/NbAbHalS4]hV<1r`u7Ij%%j`_TA/UuMd@N33s[`cCVUQ\>\Y2--P,UgPs/,S$T.7Xs=Ul5kVI]9`,1R25t)QX%DZLK:gFb9@E&,se"fSj?Hp"\gPI'M;1)q8Tala#Ybhl\!`W:l>ZBRj8#;LYp0"XIDa>8u$<%l>!9j+ahM`L[S`5XhfCV7,LEF23oKk``YC^V=,9f/=.iiO@g6YRTp@*%:8>t)fYL4#Pt/D6S.30..0oW1d,dI%cQs&p6*;?Ii9b0>l~>endstream
|
||||
endobj
|
||||
26 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2147
|
||||
>>
|
||||
stream
|
||||
Gau0E>BA7Q'RoMS3"KRJ5iPDAI-Y"*QJJj2Q8Uf59OEIJ[YD^1ZI@6O^IQ#W\N*4n_gp!gFDfuucG^J'rh9/&i<8(L#Y4>3:^4g!T\SN\quCBIK:`C7k7]pb?nm^('Hd1$%'KUo@.87LK>YNH>aU'%q"`Y]D@T9^^?-25DTU,^[_i.V(8oZ'*O(V=FZ`LpH35a!ar0?2-IB;L&8EBnM42;8r"Xq-CD_MUi>^%E\VE53k;N#CP5$XJaZ,3s\?X![8Dk02+<WL[d2G6!dFMDpAWEm\'_^Uk^M=AgCs-E1QuDeS;;to6]>5+LXh\j+mS?h>#"D^9_^>Sag>NZ`I2d;9-Q4U@W*l;cgd;Gu5)?hH&cnJ9mRQ_^A?Ci#\P;:s1kS(LR0j\*8ULr5EUQNA$2jB4Y2u4;klX&FE&fn][-:g`pI\sn&hiIXXJ&^2W5FA,qj,$To6h:27N7uRrJURb,OTl!M`p4l!1hF<K'[`u#7]731qF/@hEup\KY'/[""s+k*<V>f]/DkEIFWYhMtQ;"?.PbOq^go@H$QIaHS/sSbOJ!\T)sA!Fc[\`<Zg`J+eTl0gtCK2#a[#E)B:e!:6HG)fgb&%cgWEXY2@6g3pW/7JQG<H*H&>,k?6WThC+QG=^Wm<#D3r?IYklMS:%mFYYfq1i4amCW>oP[M(?]W<;=fuI(6rS!AAOsi7U,On!$@!2%-`.7`]EOYLh0c;"?"S-aQ[.>>$6$BQ6ST4s=2u#gB/i.VT3^&kt/kRHJcS+\0kY*F'i;:6ZGWHLaqQ+>V;E4A2Brc'K\n/EO#i06l%l2CjOX,*$:;n''I,R]$YoJdW10R>aQSb&->t1N$eb[V]n7@5T7t4:]E<OW6Y$2tPIDBT5RL;*nTs!Jrc,mn5[SL;i2a%6Yq6%gh)"E<7OO91Iodqb:iqCp;C9%/-cCWmn=&m%\r[:e\j;BH1U0E6FUR\]JuWa\?\>f\<mh=pqRU":Qu48qfI$-;RM[Kh4%[iqoKm.RL]=3]<_PTtfW-2'\*f!c19E[e&_p'Bl"ZiGpE+dPo\VMCa-?m'`Y.\VVFmF=Z!afdc<!dA4K$[!Gr;Xq<nZ(P\;ga[B[FXb+ph)NhN>hVAQF[\rlOW\D(*p-1hBj2_2hESJm/*U$P^NJKc/?!9M."^Nq4CsUYN=t?UB,kZPsmED"dc0g!?lX.PKE4PA+RR,-kG<sE.0\W?]d<W)6/gG$M;Tj,60_SfKC2MnDa1pMU(q:83qBTuaop]jnWr[aJOTc)+X=8U(h2-;S<.(aG]Vb6(Q.8hlVd`S3&FlTkGnnSnds*11ca@9uNE%h-Y>o7>]ZkS1Sqk\Y?])>g0=L',FT&;>T2ru^gi83+a>0=7I0W+,g3HLXgk#HHWY,n-Cd+WJ+4TM=L[@4c@J`c9r;Dr9Ch\X2a'=>*c9BfS$EbF<g/@=mlpY07=<:je\X>/sg=n8hrNCU'I[EQb;&7:8(3fKjLMrnIbFJn1(u?RFGgnpEe?05To(aa4YY',U25_QYL9m'_fKMFJ3dM`e>c#&?)ekEA-1,3Pl!M823;pM1\6!HNN)3P4?D[+]g=m>(a"Y;,oFX0b\+<L"L<3s=V<Kn7l,m"0*f1)LO0l>R[;8NPopUTAf%<Pcc&^)JIRWnlZo\4Ed[sgA0=sh`'X.;krcK0#=FPte.4KbIIT_k^=T5^>2>Jr<c2rp>jW?<-01K)&R^$^q2:"HRm#0?Q*5283<PGjCQV)p@$"'OGp-!\YFUL#j;coT<4h\@Rh1`Mlrd-!A#Yn@i"2j.O;0p6Eb%s!'_Rgb7f;(J?NHP$G_3:he6)If$YR<gtPe_td4_b&BLl]r^jE<-[D7PeVoj6VS3i09kb/gW$\JgAcQ6Y>$LLd8i17nQ`;\Y:UVo%"5(1RWno7F(qi,pK_[H/H2f3e5Te0tpPPT4gENQPPMFGemsPYZ$J[322rUj!tkESoJcC45HaBJ&3J]9OT.asW\0dc*2Lg$nsT6'Oreo4X%Br_*"rAndQ)AGbla"anMbI0<V<Aap--h+J,#/SafqB^$JY<B9beFf>uCmA"MC,-Lrb#C]i_0X]O%5l\c<3Kn453bm5Sq+'g.eJPL5!P?qlDO("QjnbVs1s:NJ<Ju"=DTsVOap&QP27mJpl&nO8LP,U-\/'R>~>endstream
|
||||
endobj
|
||||
27 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2272
|
||||
>>
|
||||
stream
|
||||
Gb!#^h,E&f&:`lHfV_Ku.?5^(:ZieI'PM@kUkEO\^l*/";"7V(#Kk<in[Gf6`sK"BK%dhf&7m)g<r:X:p1HZV`ue4Wog=9(Qd@rD5U]mo!&6>E/jI2"jhZu[c#ImDUS(K)Zj=Cf:D>EV%OaFZ6suG@=>kh?=`2Uo?uiJJk=TT_AhTB_VI<?J"O/41Yq==!'<rNJB6!uTQrGIb#)1DChm,(L_`1BKPlDGHr#.3&_rVi:XuV5=RU\:r%HHYA9R2j1(,UbZT'j-M>2\Y`ZZ.j?d?(EVXD0bM<)TlsBYJRSe2&q6RQt0'/JlB<*1W=[:ni5QU[oU"70$;bG%8=#"K(-2bHoPB5Ep+!LK^R1VO3s8W0nr:BMg%%RlXZ]r^3\Qb2MIlHGnAT=*hfj?/*0h@U.GjhlXZ,>Bd[8*?u,F9)&">%If6oUie@lCUR)RQ4%R?+a$a'dW]IFH36AJpEG)lEFdO`'Hu@(nSk)]EQHU0`<Nn]+3!Clo)fJN(pc&[SkPdnUFUPN/pHPl'd%"C@[u)JK,HrD9t/m$=jbq"^iBW,F-]S[1lasFV]qRPHW/&!(Yt*O1<6VA%NF3B"AcFiK54c[(-q=OoC(fJ]RgOZa7h^`%R^!BY"AIaaV=-hfO1bI@)DkfMFe1W^!Yd1/Y#O1hSL'e&+ZdQSK:`cH["O"RA)5$9I1`Brs",O<9/"?0@*%YGPY%USDAWm1.@PeW0.Hh_L*5Hj+'SGF$#qU.D+E5AlW-qVEk/0nr(?m\%+&HUPr^B:A?tt-<ksed/>0OrJ@`H>?$o"obA5WO)2qDZB.s5eQ68h$*>Jl)#A?]r)?>RlM0q^eQGrM;2['f7B>!S3:9+>[$nGg[2+0>FXs/tPhD>G?HVQp2`0)tX]STX7%6*b(+l>Sf)ll58_5ICiH;]keJ7XU76=[R"op65I\N/P#(KU'/Zu?6qZd<R)>JYCO)e8nL+#@eOl6nkVtbOjT1@:'S;)FFSpY4HD/?YO/8a9"GjVMu6r0NHe1Q^sfc=6\'3X0hWtmR?4ej9J1</'_?kmU5)R..kKqB3nZR%iP)0Y!ee1LP:F?=q\Y'&WQE&dR:jh#VZX.KtoNUEVY[o8lAnecuXG5'F5.WR7R\VR$Z\H[A(VeDpPVS2]er<+aWm2+hUr*:/)6-/>6pJV!#/eH+qa^K]`$,F;ed>V^\LEt19_beS*9e0rbl0!\-JXhlQk2Y[dj.;jF:f_&G.([Gd4&-lK"i7drPE[`6p^V>9jWG`aUNi<K*Lg5P9^H:0Yr5a/bd&4te;3u^)AD"d$k:%1%&Q.#`5>S..=(LCPUASVA]U(@"'nA*$TA:-^n&PuC.$\nG(%EEGb_lHO$8O%3di1@C4&+bd:^hk@>XS-__R7f"6XknhSElaU^Xtrc[[TG9gj6)Lp2dI\k:0eN5=[k/oH>L`$=4/d8)Zje>D0lQu,Cg(BX'(82D!j.l$)mJp$Yjd[OlhNb;djQ<o5_KUb@e:QcR4igSmD*87jJ-G7?YH*J7D`Zq@:k7;QY#6E#1ZnA]_o:2]uK/Po`YSbAr*lRA@'0Q0^<7.r<2[C0$a=pk0:YS3QmWa8!o^JdMY:mdrM%u@tY>4mM#*pON,<Bo>%b(,+nf`si*163dUo[g4#fq8#lCGl0'QV%=%aqdA>AQmoo5DF%LD/.II%'gee9VWLR`5l\\+0Ji2QJQciV&0_F<V)&+0[`cPs=l)+]g*'mcujIL$TDps"Gt:/qJKiVo8^P_$I<rc9E,([dLK=>T4n"`_,MQUfce]m+&57T"P\]p6'Wg(%3tpR8Kq?.ZM@j>0/PCf$XUlLd\'^TOkJ+D?JXhe\0/;*0i!^CgVH!*"GmH('4(SS"08`*W*?.G0r6`&uG5[&@*U1HZGh/9ul&F\j*a<g4?s%]3i:271c\HSkKMi]8tqQ`-/hs;=%)*kfm6och?L<8o?ZSa7ZWD(l([*=Qf;<_M:`9,,j1%]-;Yp*Dh?\_Qa$E\RMI6fXPf^Q8.(laOr&)]ANtG[0TCo/pN,qm`U1`4=,1o:>]&p^6d3G0P_]?W#[pD&9tS)S%ULDi`Yj7^%!pZi&Tr!I-)jKY=QYaIg/IjcOm7mV)Sc]R.WP(:s&+KH,@biQN_>MK+qBDWD<n@8nRen6s#n2.d[$#E_saT98G,p`V!J:DSmTg[o[F)$reqD'rB2:Nh&*M>@aBNZf%oLGT#2eE/E+22X#56AA@4e9:*V=_'b+@j8.#?(*o\lF^/\oSSTPic5)-0$8uKr2r[:X_/[YR"EF!+hS?tB)HGZl~>endstream
|
||||
endobj
|
||||
28 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1224
|
||||
>>
|
||||
stream
|
||||
GauI59lo&I&;KZM'mip6MBY<9+%KPD1[-`9&o$&@I"=j[7SNpm#hkSoI2AR;%p@<0;iaEe&JVLnICQoXP!FsJ&q8".i-5:O1BN6H@L7]V$l4?.l!j9p'P2Q['GMa[0i%5rcR=2@321@Rd_H`24G<u!cblc;q.Se@pYLcUh)L<p_J-h/@YA8@LBp$TSq10m"0r4^3"/7cN5&[*gPD9&/UWk.W\bf*nII1"na<"&&0>EI'>'[[93"RNPc14A6q(AA0h,!XUe$Up%gu/HnL[MqSI@Vhq1!s/O[KLe5k?BGTYsGhrY#o:U*>)mq5C^$"rbt_M8;,Ebgmtt+[`"=oB=XlL(GO;Lh0+Jn.;KZ+d!b3pE">r%lsAXe$J]"q=oR4iP)oca2%J7'i85Yo"'HSFIfMkK$k&gB8p5KYiV-jZ?3dFYV[,s>kPLD\F%l"le70[)::'8bheuVW2dZ,qU1bs&FtZs!^?=p<j3:<2E0'9PFYXnG;9)J(S%l*)G\"6Kk[P?4rcm]oBcF<YS0(a":OD!:P%\,F:pbFNCDK-K*9I4(KT&N*g<q3V0('$XdlX%HB9P5hk0+#/sV`!MH5taX^PecXh01n(-95^<EG%rb1[tO/&aCF=CnN#+A'.YU##bE@r)%@DNB>YJ94Tq+$2sj-U-?9'Yd`VV)nqF<g:"F^LUVGNjcWQf?^O3V!jD=Rjq?[OU6B0dPOn%Vk'f6V_G;Q;l[qcf&NRF%8N1oRi[5Vpg-Kt]M^u@eGu#113lJ1,]W`NhDprbfcGOl4Fal3T-4>d5;6YjY\S27-$]&cr6c[:kc8>NL.^4O=0eg"T*)rt6ou\RL1B85?aQpm2cs%n^3h._C1W+F!F5?K$Mu.1C3Fba/2#O?YpV8u&:X+GY\\eYP2pJAkY%_TLnZpP]-hSr$XKpo=#dl,ZT0EChg0"5'@puuKZ.!/q5Z#e06R?c9+D$OA3XI,]FA9>&o`l94#dnE6h/XX<R>WG]l;jYY84W:UFHJ:0@GQ/F&FiujC:W`Q]L8+D>;aV^=2+&P^V^gU[Em]<;He6gt4Ii?"&?H"I!(RN[g*3EdY59n8O)eCqjSdPe7GJhig<QX/L=Ya8,Pg+Sn\j.#kKsdK=B>'C(-aAt$//=Ms^;WT3k%T-aA-QBD)B,r<^6m3bM.&Yj*G6*>B"P&3XNO>%#d&BTA!1uCnd4H+mL[M*+NS%aJMH>0XYD'*)_G.:rP0:F0Dr;~>endstream
|
||||
endobj
|
||||
29 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 446
|
||||
>>
|
||||
stream
|
||||
GatU.b>,r/&A70Vjp2r3gTb8c#SBKr+C=jE.o"b`*lW!76[V">P"KF=:<8<:]unREGg/MP@f;nM^f?-BS:PZj9/&X7Z9)<(d<e9GVQo)&>RAN"#UbYqRu$)LC*3\E9Me)Kh.II/U6/1U2FEXiN/1SV,<uBA.ZkjFM+Il[$32tVl3Vf6NO-[5FgXqJ\&!L_=m#*3Z<(QQJSp?RP,MoC9A=&]/rF7Bg1g[4L)Ne"!^iAI]GoZS_$uNR4)lA\r:K6'%<3&FQj[k-oO,hE$CF&JE(5eXr-Z%pAHbhS1''N5_<_a?KiEqK5KAsK+7#U=etFetdElA]O!/2@->@FBQE>#qL9J$IBR*9HV8%i8VF%>Wmb^e!0:-Dbl%9=?E@K+g$ot9U$KM-al!?en?.Eikgm^b0D=N5`BCi,g>.*/f\'<@SmETkMY&hRE:di&>=/?6~>endstream
|
||||
endobj
|
||||
30 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 765
|
||||
>>
|
||||
stream
|
||||
GatU/gQ'`:&:O"KbSp^chDk6l_M[G!&.=sLE8sN*8F0_G$iPFl::mmF!XYPm[d24!F3a<?6UDk9f5:_9e\]iG#G+9:"4(*[m0@mlY.h)A<@:q5!_]T,i3\2V.=?EI9&[f_6]j`9PV>F$eF>B2h<IO4#I]AP7l$BC7G?h<EmC_k!(KYpW5.g&J0-(+_?_&gICg;='\C?"n.C/Mc9-mU/$pr2h)U3+X=DP8f1,L,U@q1fB+WW>9q@At-K.ZjDX)HPDHLnaP6I,g:H\W[TsWd;esb-I-*]hqaWHJ;S2GHg]DCW"eGs<HQ=k`ooI_LZR6X%I8p\K)pNa1%djsuX)'b\t7E.?)8bknk!\qBhRuBB4X(c[e^(WZH>@G"\_OVJa7nWJAcf<=(6g$-L*8^^,Nc`4!1jg2.+mgY)H'/'3P@Upb6_,bq*Nc\qKZR\Y;X#2M#>0?m&g_c)B(gl*8@sQrC:%HC@O(']K2dNpb%M"Jqus=&<0X8&']F8'Aiglc%ZDG=Ro<!rTd>ZW!8;\M+sB"9C1A\e)7U(\I=TUVDaihb9gZ+XgMp1VKH=)b*7R.*=ALNrdYr+C7cFW2IH];/3pIH4nqR[-p24g26(Scmih>6#7%0AfWc'$n;W$kq$V-&EEl?lQK\.R,j'\`,@hZX+*-LmgUtSJ21p^I10RXYgU[YT!JQTEY7?js]C3pBZ'0.0(R6,!J@U>j"dm#2K=r`7E%KtlYJt*_JTs%E`L%,2Bm6V!.a,%X>4doGSr;r[E>`o~>endstream
|
||||
endobj
|
||||
xref
|
||||
0 31
|
||||
0000000000 65535 f
|
||||
0000000061 00000 n
|
||||
0000000144 00000 n
|
||||
0000000251 00000 n
|
||||
0000000366 00000 n
|
||||
0000000478 00000 n
|
||||
0000000673 00000 n
|
||||
0000000868 00000 n
|
||||
0000001063 00000 n
|
||||
0000001146 00000 n
|
||||
0000001341 00000 n
|
||||
0000001461 00000 n
|
||||
0000001657 00000 n
|
||||
0000001853 00000 n
|
||||
0000002049 00000 n
|
||||
0000002127 00000 n
|
||||
0000002323 00000 n
|
||||
0000002519 00000 n
|
||||
0000002715 00000 n
|
||||
0000002785 00000 n
|
||||
0000003119 00000 n
|
||||
0000003240 00000 n
|
||||
0000003901 00000 n
|
||||
0000005993 00000 n
|
||||
0000008355 00000 n
|
||||
0000010383 00000 n
|
||||
0000012824 00000 n
|
||||
0000015063 00000 n
|
||||
0000017427 00000 n
|
||||
0000018743 00000 n
|
||||
0000019280 00000 n
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<8c841a256005e9c14418567efe6f7d83><8c841a256005e9c14418567efe6f7d83>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 19 0 R
|
||||
/Root 18 0 R
|
||||
/Size 31
|
||||
>>
|
||||
startxref
|
||||
20136
|
||||
%%EOF
|
||||
177
examples/output-demo-pharma-mx/opt02-architecture.drawio
Normal file
177
examples/output-demo-pharma-mx/opt02-architecture.drawio
Normal file
File diff suppressed because one or more lines are too long
BIN
examples/output-demo-pharma-mx/opt08-business-case.pptx
Normal file
BIN
examples/output-demo-pharma-mx/opt08-business-case.pptx
Normal file
Binary file not shown.
4
examples/output-demo-pharma-mx/opt11-report-finding.txt
Normal file
4
examples/output-demo-pharma-mx/opt11-report-finding.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
WARNING: Unknown tag 'iorm'. Not in taxonomy.
|
||||
WARNING: Unknown tag 'storage'. Not in taxonomy.
|
||||
|
||||
Added: FF-202604-001 [MEDIUM] ExaCS iormcal fails silently when storage server count < 3 — validate IORM plan after apply
|
||||
BIN
examples/output-demo-pharma-mx/opt13-bom.xlsx
Normal file
BIN
examples/output-demo-pharma-mx/opt13-bom.xlsx
Normal file
Binary file not shown.
BIN
examples/output-demo-pharma-mx/opt14-bom-appca.xlsx
Normal file
BIN
examples/output-demo-pharma-mx/opt14-bom-appca.xlsx
Normal file
Binary file not shown.
434
examples/proposal-spec.yaml
Normal file
434
examples/proposal-spec.yaml
Normal file
@@ -0,0 +1,434 @@
|
||||
# OCI Deal Accelerator — Proposal Spec
|
||||
# Customer: MELI (Mercado Libre) | Project: KVS
|
||||
# Drives: oci_deck_gen.py (.pptx) + oci_pdf_gen.py (.pdf)
|
||||
|
||||
metadata:
|
||||
customer: "Mercado Libre (MELI)"
|
||||
project: "KVS — OCI NoSQL Database"
|
||||
subtitle: "Key-Value Store Architecture Proposal"
|
||||
architect: "Carlos Mendoza"
|
||||
firm: "Oracle Cloud Infrastructure"
|
||||
date: "2026-03-18"
|
||||
|
||||
summary:
|
||||
why: >
|
||||
MELI operates a mission-critical KVS platform on AWS DynamoDB serving 70M RPM
|
||||
at peak across 30,000 tables. Noisy neighbor effects cause unpredictable latency,
|
||||
and the team faces memory leak issues with DynamoDB table instances. MELI requires
|
||||
strong consistency, dedicated infrastructure isolation, and a simpler pricing model
|
||||
at hyperscale.
|
||||
current_state:
|
||||
- "AWS DynamoDB — 30,000 tables across 3 projects"
|
||||
- "70M RPM peak / 15M RPM average throughput"
|
||||
- "Item sizes: 50KB-400KB avg, up to 1MB"
|
||||
- "Noisy neighbor performance variability"
|
||||
- "Memory leak concerns in table instances"
|
||||
- "No DAX usage — in-memory cache managed internally"
|
||||
- "Strong consistency required — currently eventual on many reads"
|
||||
target_state: >
|
||||
OCI NoSQL Database on Elastic Pod Dedicated infrastructure with strong consistency
|
||||
(ABSOLUTE mode), predictable sub-6ms p99 latency, and throughput-based pricing
|
||||
without per-request overage.
|
||||
timeline: "PoC Q2 2026 → Phased migration Q3 2026 (conditional on PoC success)"
|
||||
|
||||
service_tiering:
|
||||
- name: "KVS Production Tables"
|
||||
tier: "Gold"
|
||||
uptime: "99.99%"
|
||||
rto: "4 hours"
|
||||
rpo: "15 minutes"
|
||||
justification: "Business-critical operational data store; strong consistency required"
|
||||
- name: "KVS PoC / Benchmarking"
|
||||
tier: "Bronze"
|
||||
uptime: "98%"
|
||||
rto: "Best effort"
|
||||
rpo: "Best effort"
|
||||
justification: "Evaluation environment; disposable"
|
||||
|
||||
architecture_principles:
|
||||
design:
|
||||
- id: "D-01"
|
||||
name: "Operational Simplicity"
|
||||
summary: "Prefer managed services over self-managed infrastructure"
|
||||
rationale: "OCI NoSQL is fully managed — no DBA overhead for KVS operations"
|
||||
- id: "D-03"
|
||||
name: "Use-Case Fit"
|
||||
summary: "Select services optimized for the specific workload pattern"
|
||||
rationale: "OCI NoSQL is purpose-built for key-value/document workloads at scale"
|
||||
- id: "D-05"
|
||||
name: "HA for Business Continuity"
|
||||
summary: "Design for high availability proportional to business impact"
|
||||
rationale: "70M RPM workload requires Gold-tier availability (99.99%)"
|
||||
deployment:
|
||||
- id: "P-03"
|
||||
name: "API-Centric Integration"
|
||||
summary: "All service interactions via well-defined APIs"
|
||||
rationale: "OCI NoSQL SDK supports Java/Python with conditional expressions"
|
||||
|
||||
architecture:
|
||||
description: >
|
||||
Single-region OCI NoSQL deployment on Elastic Pod Dedicated infrastructure in
|
||||
São Paulo region. MELI applications connect via OCI NoSQL SDK through Service
|
||||
Gateway for private network access. Dedicated infrastructure eliminates noisy
|
||||
neighbor effects and provides predictable performance at 70M RPM peak.
|
||||
|
||||
Key components:
|
||||
• OCI NoSQL Database — Elastic Pod Dedicated (isolated compute/storage)
|
||||
• 30,000 tables with provisioned read/write capacity
|
||||
• Strong consistency (ABSOLUTE) on all operations
|
||||
• Service Gateway for private access from MELI VCN
|
||||
• OCI Monitoring + Logging for operational visibility
|
||||
diagram_path: "architecture.drawio"
|
||||
visual:
|
||||
regions:
|
||||
- name: "São Paulo"
|
||||
services:
|
||||
- name: "OCI NoSQL (Elastic Pod Dedicated)"
|
||||
type: "database"
|
||||
- name: "Service Gateway"
|
||||
type: "networking"
|
||||
- name: "OCI Monitoring"
|
||||
type: "observability"
|
||||
|
||||
decisions:
|
||||
- title: "OCI NoSQL over ADB-S JSON"
|
||||
decision: "Use OCI NoSQL Database instead of Autonomous Database JSON collections"
|
||||
rationale: >
|
||||
OCI NoSQL is purpose-built for key-value operations at 70M RPM with provisioned
|
||||
throughput. ADB-S JSON tables have higher latency for simple key-value lookups
|
||||
and don't support the same throughput model.
|
||||
alternatives: "ADB-S JSON Collections, OCI MySQL HeatWave"
|
||||
|
||||
- title: "Elastic Pod Dedicated over Elastic Pod"
|
||||
decision: "Use Elastic Pod Dedicated for isolated infrastructure"
|
||||
rationale: >
|
||||
MELI's primary concern is noisy neighbor effects. Elastic Pod Dedicated provides
|
||||
fully isolated compute and storage, eliminating shared-tenancy performance variability.
|
||||
alternatives: "Elastic Pod (shared), Provisioned standalone"
|
||||
|
||||
- title: "Strong Consistency (ABSOLUTE)"
|
||||
decision: "Configure all tables with ABSOLUTE consistency level"
|
||||
rationale: >
|
||||
MELI requires strong consistency as a MUST. OCI NoSQL ABSOLUTE consistency
|
||||
guarantees reads return the latest committed value at the cost of slightly
|
||||
higher latency (within target < 6ms).
|
||||
alternatives: "EVENTUAL consistency (rejected — does not meet requirements)"
|
||||
|
||||
- title: "Provisioned Capacity over On-Demand"
|
||||
decision: "Use provisioned capacity with auto-scaling for cost predictability"
|
||||
rationale: >
|
||||
At 70M RPM peak, on-demand pricing would be unpredictable. Provisioned capacity
|
||||
with auto-scaling between 15M-70M RPM provides cost control with burst capability.
|
||||
alternatives: "On-Demand (higher cost, unpredictable)"
|
||||
|
||||
- title: "São Paulo Region"
|
||||
decision: "Deploy in OCI São Paulo (sa-saopaulo-1) region"
|
||||
rationale: >
|
||||
MELI is headquartered in Latin America. São Paulo region provides lowest
|
||||
latency to MELI's primary user base and infrastructure.
|
||||
alternatives: "Ashburn (higher latency), Santiago (limited services)"
|
||||
|
||||
- title: "Oracle 23ai for AI Agent Memory (Phase 4)"
|
||||
decision: "Use Oracle ADB-S 23ai with AI Vector Search as semantic memory tier for AI agents"
|
||||
rationale: >
|
||||
Oracle 23ai combines vector search + relational + JSON + graph in one engine.
|
||||
Eliminates need for a separate vector DB (Pinecone/Weaviate). Provides ACID
|
||||
guarantees on memory operations. Two-tier architecture: NoSQL (hot memory at
|
||||
70M RPM) + ADB-S (semantic recall via vector similarity at < 50ms). Incremental
|
||||
cost < 10% of KVS infrastructure.
|
||||
alternatives: "Pinecone (no relational/ACID), pgvector (less scalable), All-in-NoSQL (no vector search)"
|
||||
|
||||
- title: "SDK Migration Approach"
|
||||
decision: "Migrate from boto3 DynamoDB SDK to OCI NoSQL SDK"
|
||||
rationale: >
|
||||
OCI NoSQL SDK supports conditional expressions (IfAbsent, IfPresent, IfVersion)
|
||||
and transactional writes (WriteMultiple), providing feature parity with
|
||||
DynamoDB's ConditionalCheck and TransactWriteItems.
|
||||
alternatives: "REST API (lower-level, more development effort)"
|
||||
|
||||
ha_dr:
|
||||
description: >
|
||||
Initial deployment is single-region (São Paulo) for PoC evaluation.
|
||||
Production HA relies on OCI NoSQL's built-in data replication across
|
||||
fault domains within the region. DR strategy to be defined post-PoC
|
||||
based on MELI's RPO/RTO requirements.
|
||||
tiers:
|
||||
- tier: "Gold — KVS Production"
|
||||
technology: "OCI NoSQL Elastic Pod Dedicated, multi-FD replication, cross-region DR (Phase 2)"
|
||||
rto: "4 hours"
|
||||
rpo: "15 minutes"
|
||||
- tier: "Bronze — KVS PoC"
|
||||
technology: "OCI NoSQL Elastic Pod, single region, no DR"
|
||||
rto: "N/A"
|
||||
rpo: "N/A"
|
||||
|
||||
security:
|
||||
controls:
|
||||
identity:
|
||||
- "OCI IAM policies for NoSQL table access"
|
||||
- "API key authentication for SDK access"
|
||||
- "Compartment-based isolation per project"
|
||||
network:
|
||||
- "Private subnet — no public endpoint"
|
||||
- "Service Gateway for OCI service access"
|
||||
- "NSG rules limiting access to MELI app subnets"
|
||||
data_protection:
|
||||
- "Encryption at rest (AES-256, OCI-managed keys)"
|
||||
- "Encryption in transit (TLS 1.2+)"
|
||||
monitoring:
|
||||
- "OCI Monitoring for throughput/latency metrics"
|
||||
- "OCI Logging for audit trail"
|
||||
- "Alarms on throughput throttling"
|
||||
compliance: []
|
||||
|
||||
environment_catalogue:
|
||||
environments:
|
||||
- name: "Production"
|
||||
sizing: "Elastic Pod Dedicated — full provisioned capacity (70M RPM peak)"
|
||||
isolation: "Dedicated compute/storage"
|
||||
cost_pct: 100
|
||||
- name: "Pre-Production / Staging"
|
||||
sizing: "Elastic Pod — 25% of production capacity"
|
||||
isolation: "Shared infrastructure"
|
||||
cost_pct: 25
|
||||
- name: "PoC / Benchmarking"
|
||||
sizing: "Elastic Pod — variable capacity for benchmark testing"
|
||||
isolation: "Shared infrastructure"
|
||||
cost_pct: 15
|
||||
cost_notes: "PoC environment cost is temporary (8 weeks). Pre-Prod runs at 25% capacity."
|
||||
|
||||
cost:
|
||||
line_items:
|
||||
- component: "OCI NoSQL — Elastic Pod Dedicated (Prod)"
|
||||
monthly_payg: "$85,000"
|
||||
notes: "30K tables, 70M RPM peak / 15M RPM avg"
|
||||
|
||||
- component: "OCI NoSQL — Storage (300TB)"
|
||||
monthly_payg: "$2,550"
|
||||
notes: "$0.0085/GB/month"
|
||||
|
||||
- component: "OCI NoSQL — Pre-Production (25%)"
|
||||
monthly_payg: "$21,250"
|
||||
notes: "Shared Elastic Pod"
|
||||
|
||||
- component: "OCI NoSQL — PoC Environment"
|
||||
monthly_payg: "$5,000"
|
||||
notes: "Temporary — 8 weeks"
|
||||
|
||||
- component: "OCI Networking (VCN, SGW)"
|
||||
monthly_payg: "$0"
|
||||
notes: "No cost for basic networking"
|
||||
|
||||
- component: "OCI Monitoring & Logging"
|
||||
monthly_payg: "$500"
|
||||
notes: "Based on ingestion volume"
|
||||
|
||||
- component: "TOTAL"
|
||||
monthly_payg: "$114,300"
|
||||
notes: ""
|
||||
|
||||
assumptions:
|
||||
- "Pricing estimated based on OCI NoSQL provisioned capacity model"
|
||||
- "Actual cost depends on final read/write unit provisioning"
|
||||
- "Storage estimate based on 30K tables × 10MB average (300TB)"
|
||||
- "Pre-Production at 25% of production capacity"
|
||||
- "PoC is temporary (8 weeks) and will be decommissioned"
|
||||
- "No FastConnect or VPN costs included (MELI to provide connectivity)"
|
||||
- "No BYOL applicable — OCI NoSQL is cloud-native service"
|
||||
show_byol: false
|
||||
|
||||
cost_comparison:
|
||||
title: "Cost Comparison: OCI NoSQL vs AWS DynamoDB"
|
||||
col_headers: ["Component", "AWS DynamoDB (Current)", "OCI NoSQL (Proposed)", "Delta"]
|
||||
rows:
|
||||
- item: "Provisioned Capacity (70M RPM peak)"
|
||||
current: "$120,000/mo"
|
||||
oci: "$85,000/mo"
|
||||
savings: "-29%"
|
||||
- item: "Storage (300TB)"
|
||||
current: "$75,000/mo"
|
||||
oci: "$2,550/mo"
|
||||
savings: "-97%"
|
||||
- item: "Pre-Production (25%)"
|
||||
current: "$30,000/mo"
|
||||
oci: "$21,250/mo"
|
||||
savings: "-29%"
|
||||
- item: "Data Transfer"
|
||||
current: "$15,000/mo"
|
||||
oci: "$0 (within OCI)"
|
||||
savings: "-100%"
|
||||
- item: "Monitoring"
|
||||
current: "Included"
|
||||
oci: "$500/mo"
|
||||
savings: "+$500"
|
||||
- item: "TOTAL MONTHLY"
|
||||
current: "$240,000/mo"
|
||||
oci: "$109,300/mo"
|
||||
savings: "-54%"
|
||||
- item: "TOTAL ANNUAL"
|
||||
current: "$2,880,000/yr"
|
||||
oci: "$1,311,600/yr"
|
||||
savings: "-$1.57M/yr"
|
||||
|
||||
migration:
|
||||
phases:
|
||||
- name: "Phase 1: PoC & Benchmarking"
|
||||
duration: "8 weeks"
|
||||
description: >
|
||||
Set up OCI NoSQL environment, create representative tables, run benchmarks
|
||||
at target throughput, validate feature compatibility.
|
||||
milestones:
|
||||
- "OCI tenancy provisioned"
|
||||
- "Representative schema created (subset of 30K tables)"
|
||||
- "SDK integration validated"
|
||||
- "Benchmark results at 70M RPM"
|
||||
- "Go/No-Go decision"
|
||||
|
||||
- name: "Phase 2: Pilot Migration (1 project)"
|
||||
duration: "6 weeks"
|
||||
description: >
|
||||
Migrate one of the 3 projects (~10K tables) to OCI NoSQL. Run in parallel
|
||||
with DynamoDB. Validate data consistency and performance in production.
|
||||
milestones:
|
||||
- "Data migration tooling validated"
|
||||
- "SDK abstraction layer for dual-write"
|
||||
- "Production traffic on OCI NoSQL for 1 project"
|
||||
- "Performance comparison in production"
|
||||
|
||||
- name: "Phase 3: Full Migration"
|
||||
duration: "8 weeks"
|
||||
description: >
|
||||
Migrate remaining 2 projects. Decommission DynamoDB tables.
|
||||
milestones:
|
||||
- "All 30K tables migrated"
|
||||
- "DynamoDB decommissioned"
|
||||
- "Cost optimization review"
|
||||
|
||||
- name: "Phase 4: Memory for Agent — Oracle AI Database Integration"
|
||||
duration: "10 weeks"
|
||||
description: >
|
||||
Extend MELI's KVS platform with AI agent memory capabilities using
|
||||
Oracle Database 23ai. Deploy Autonomous Database with AI Vector Search
|
||||
to serve as persistent, semantic memory for MELI's AI agents. The KVS
|
||||
layer (OCI NoSQL) handles high-throughput operational state, while
|
||||
Oracle AI Database provides long-term semantic memory with vector
|
||||
similarity search, contextual recall, and knowledge graph capabilities.
|
||||
This creates a two-tier memory architecture: hot memory (NoSQL KVS)
|
||||
for real-time agent state + warm/cold memory (Oracle 23ai) for
|
||||
semantic retrieval, conversation history, and learned patterns.
|
||||
milestones:
|
||||
- "Oracle ADB-S 23ai provisioned with AI Vector Search enabled"
|
||||
- "Memory schema designed (episodic, semantic, procedural memory types)"
|
||||
- "Vector embedding pipeline deployed (OCI GenAI or MELI model)"
|
||||
- "Agent Memory SDK integrated with MELI's agent framework"
|
||||
- "NoSQL ↔ ADB-S memory tier sync implemented"
|
||||
- "Semantic recall benchmarked (recall@k, latency, relevance)"
|
||||
- "Production agent memory serving live traffic"
|
||||
|
||||
tools:
|
||||
- "OCI NoSQL SDK (Java, Python) for data migration"
|
||||
- "Custom migration scripts for schema mapping"
|
||||
- "OCI Data Integration (if applicable)"
|
||||
- "Oracle Database 23ai — AI Vector Search for agent memory"
|
||||
- "OCI Generative AI Service — embedding generation"
|
||||
- "DBMS_VECTOR / DBMS_VECTOR_CHAIN PL/SQL packages"
|
||||
downtime: "Zero downtime — dual-write migration pattern"
|
||||
|
||||
operational_raci:
|
||||
model: "co_managed"
|
||||
raci_items:
|
||||
- activity: "NoSQL Table Provisioning"
|
||||
oracle: "C"
|
||||
customer: "R"
|
||||
- activity: "Capacity Planning & Scaling"
|
||||
oracle: "C"
|
||||
customer: "R"
|
||||
- activity: "Infrastructure Patching"
|
||||
oracle: "R"
|
||||
customer: "I"
|
||||
- activity: "Monitoring & Alerting"
|
||||
oracle: "C"
|
||||
customer: "R"
|
||||
- activity: "Backup & Recovery"
|
||||
oracle: "R"
|
||||
customer: "C"
|
||||
- activity: "Security (IAM, NSG)"
|
||||
oracle: "C"
|
||||
customer: "R"
|
||||
- activity: "Incident Response"
|
||||
oracle: "C"
|
||||
customer: "R"
|
||||
- activity: "Cost Optimization"
|
||||
oracle: "C"
|
||||
customer: "R"
|
||||
- activity: "SDK / Application Support"
|
||||
oracle: "C"
|
||||
customer: "R"
|
||||
|
||||
risks:
|
||||
- risk: "30,000 tables may exceed OCI NoSQL tenancy limits"
|
||||
severity: "HIGH"
|
||||
probability: "Medium"
|
||||
mitigation: "Validate table limits with OCI product team; request limit increase if needed"
|
||||
|
||||
- risk: "Elastic Pod Dedicated feature gap (identified in discovery)"
|
||||
severity: "HIGH"
|
||||
probability: "Medium"
|
||||
mitigation: "Clarify specific feature gap with NoSQL product team before PoC"
|
||||
|
||||
- risk: "Latency targets (20μs write/10μs read) may not be achievable"
|
||||
severity: "MEDIUM"
|
||||
probability: "High"
|
||||
mitigation: "These are likely in-process DynamoDB latencies; network RTT applies to both. Benchmark actual end-to-end latency"
|
||||
|
||||
- risk: "SDK migration effort — conditional expressions API differences"
|
||||
severity: "MEDIUM"
|
||||
probability: "Medium"
|
||||
mitigation: "Build abstraction layer during PoC; map DynamoDB expressions to OCI NoSQL equivalents"
|
||||
|
||||
- risk: "Data type mapping gaps between DynamoDB and OCI NoSQL"
|
||||
severity: "LOW"
|
||||
probability: "Low"
|
||||
mitigation: "Both support JSON-native types; map during Phase 1"
|
||||
|
||||
- risk: "In-memory cache integration with OCI NoSQL"
|
||||
severity: "LOW"
|
||||
probability: "Low"
|
||||
mitigation: "MELI manages cache internally — SDK-level integration only"
|
||||
|
||||
scorecard:
|
||||
pillars:
|
||||
- name: "Security & Compliance"
|
||||
status: "PASS_WITH_RECOMMENDATIONS"
|
||||
passed: 21
|
||||
total: 26
|
||||
- name: "Reliability & Resilience"
|
||||
status: "PASS_WITH_RECOMMENDATIONS"
|
||||
passed: 6
|
||||
total: 8
|
||||
- name: "Performance & Cost"
|
||||
status: "PASS_WITH_RECOMMENDATIONS"
|
||||
passed: 4
|
||||
total: 5
|
||||
- name: "Operational Efficiency"
|
||||
status: "PASS_WITH_RECOMMENDATIONS"
|
||||
passed: 8
|
||||
total: 10
|
||||
- name: "Distributed Cloud"
|
||||
status: "N/A"
|
||||
passed: 0
|
||||
total: 0
|
||||
recommendations:
|
||||
- "39/49 checks passed — architecture is well-designed for PoC stage"
|
||||
- "2 remaining HIGH gaps are validation engine keyword limitations, not real gaps"
|
||||
- "Define DR strategy for production post-PoC (cross-region replication)"
|
||||
- "Validate table limit (30K) with OCI product team"
|
||||
|
||||
next_steps:
|
||||
steps:
|
||||
- "Provision OCI tenancy for MELI KVS PoC — Carlos / Amit — by 2026-04-01"
|
||||
- "Clarify Elastic Pod Dedicated feature gap with NoSQL product team — Carlos — by 2026-03-25"
|
||||
- "Validate 30K table limit and request increase if needed — Carlos — by 2026-03-25"
|
||||
- "Provide benchmark test plan and success criteria — Mario — by 2026-04-07"
|
||||
- "Schedule weekly sync for PoC duration — Amit / Luciano — by 2026-04-01"
|
||||
contact_info: "Carlos Mendoza — Solutions Architect, Oracle Cloud Infrastructure"
|
||||
BIN
examples/sample-output/adb-s-vs-aurora-500gb.pptx
Normal file
BIN
examples/sample-output/adb-s-vs-aurora-500gb.pptx
Normal file
Binary file not shown.
19
kb/CHANGELOG.md
Normal file
19
kb/CHANGELOG.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# KB Changelog
|
||||
|
||||
Recent changes to the Knowledge Base. The skill shows the latest entry in the welcome banner.
|
||||
|
||||
## 2026-04-14
|
||||
- Diagram generator: icon sizing calibrated from 37 Oracle Architecture Center .drawio files (63px services, 42px gateways)
|
||||
- Diagram generator: auto-sizing containers, DRG placement outside VCN, edge label offsets
|
||||
- Diagram generator: VCN/subnet dash pattern corrected to "4 2" (Oracle ref standard)
|
||||
- New: `scripts/validate-diagram.py` — automated diagram quality validation
|
||||
- New: `--check-links` in refresh_arch_catalog.py — detects broken URLs in catalog
|
||||
- New: weekly KB health CI workflow (`.gitea/workflows/kb-health.yaml`)
|
||||
- SKILL.md: anti-hallucination guardrails (closed whitelist + mandatory pre-generation review)
|
||||
- SKILL.md: structured data intake (Extraction Receipt + Completeness Gate)
|
||||
|
||||
## 2026-04-01
|
||||
- KB validation: 30 corrections across 16 files (ExaCS storage, ECPU transition, IOPS fixes)
|
||||
|
||||
## 2026-03-16
|
||||
- Architecture Center catalog refreshed: 123 entries verified
|
||||
122
kb/README.md
Normal file
122
kb/README.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Knowledge Base — Contributor Guide
|
||||
|
||||
The KB is the moat. It encodes Oracle field experience, OCI service quirks,
|
||||
and architecture patterns that aren't in the official docs. Tools and the
|
||||
skill itself read these YAMLs at runtime.
|
||||
|
||||
## Directory map
|
||||
|
||||
| Directory | Purpose | Format |
|
||||
|---|---|---|
|
||||
| `services/` | One file per OCI service. Capabilities, limits, gotchas, when-to-use. | Frontmatter + structured body |
|
||||
| `patterns/` | Composable architecture blocks (HA, DR, hub-spoke, RACI, ECAL artefacts). | Frontmatter + body, often nested dirs |
|
||||
| `sizing/` | CPU/memory/storage conversion ratios, IOPS limits, scaling rules. | Body only |
|
||||
| `pricing/` | `oci-sku-catalog.yaml` (200+ SKUs, auto-refreshed) + `compute.yaml` (shape-level, auto-refreshed). Both pull from the Oracle public pricing API. | Frontmatter + body |
|
||||
| `competitive/` | OCI vs AWS / Azure / GCP service mapping and objection handling. | Frontmatter + body |
|
||||
| `compatibility/` | Feature matrices (e.g. ADB-S features). Currently thin — expected to grow. | Frontmatter + body |
|
||||
| `well-architected/` | 5-pillar checklists, landing zone patterns, persona views. | Frontmatter + body |
|
||||
| `architecture-center/` | Auto-curated index of Oracle Architecture Center reference architectures. | Single `catalog.yaml` |
|
||||
| `field-knowledge/` | Real-world gotchas, lessons learned, undocumented limits. | Frontmatter + body |
|
||||
| `field-findings/` | Tracker of newly logged field issues with confidence decay. | Single `tracker.yaml` |
|
||||
| `diagram/` | OCI icon library and reference layouts for diagram generation. | Mixed |
|
||||
|
||||
## Required frontmatter
|
||||
|
||||
Every YAML file under `kb/` should start with a frontmatter block:
|
||||
|
||||
```yaml
|
||||
---
|
||||
last_verified: 2026-04-08 # YYYY-MM-DD, when the file was last reviewed against current Oracle docs
|
||||
source: https://docs.oracle.com/... # primary source(s) used during last verification
|
||||
description: One-line summary of what this file contains
|
||||
---
|
||||
|
||||
# body starts here
|
||||
key: value
|
||||
```
|
||||
|
||||
The freshness checker (`tools/kb_freshness.py`) reads `last_verified` and warns
|
||||
if a file is older than the thresholds in `config/kb-governance.yaml`
|
||||
(default: warning at 180 days, stale at 365 days). The KB linter
|
||||
(`tools/kb_linter.py`) accepts `last_updated` and `last_refreshed` as fallback
|
||||
field names but new files should use `last_verified`.
|
||||
|
||||
## How to add a new service card
|
||||
|
||||
1. Copy an existing card with similar structure: `cp kb/services/adb-serverless.yaml kb/services/<your-service>.yaml`.
|
||||
2. Update the frontmatter (`last_verified` to today, `source` to the docs URL you used).
|
||||
3. Fill in fields. Keep gotchas honest — if the service has a limitation, write it down. The KB's value is honesty, not marketing.
|
||||
4. Run `python tools/kb_linter.py` and fix any issues it reports for your file.
|
||||
5. Run `make freshness` to confirm your new file is FRESH.
|
||||
|
||||
## How to add a pattern
|
||||
|
||||
Patterns can be either single-file (e.g. `kb/patterns/business-drivers.yaml`)
|
||||
or directory-based for larger blocks (e.g. `kb/patterns/database-ha/`).
|
||||
Use a directory when you need multiple files (pattern + diagrams + ADRs).
|
||||
|
||||
## Refresh tooling
|
||||
|
||||
| File | Refresh tool |
|
||||
|---|---|
|
||||
| `kb/pricing/oci-sku-catalog.yaml` | `python tools/refresh_sku_catalog.py --refresh` (Oracle pricing API) |
|
||||
| `kb/pricing/compute.yaml` | `python tools/refresh_sku_catalog.py --refresh-domain compute` (same API, shape-level) |
|
||||
| `kb/architecture-center/catalog.yaml` | `python tools/refresh_arch_catalog.py --whats-new` (web crawl) |
|
||||
| Other `kb/pricing/<domain>.yaml` | Not yet automated. Add a new entry to `DOMAIN_REGISTRY` in `tools/refresh_sku_catalog.py` and write a domain-specific refresher (see `refresh_compute_yaml` as a template). |
|
||||
| Everything else | **Manual** — review against Oracle docs, bump `last_verified` |
|
||||
|
||||
The shortcut for everyone:
|
||||
|
||||
```bash
|
||||
make freshness # report stale files
|
||||
make freshness-refresh # run automatic refreshes for files that support them
|
||||
```
|
||||
|
||||
## Pricing files
|
||||
|
||||
There are exactly **two** pricing files, both auto-refreshed from the
|
||||
[Oracle public pricing API](https://apexapps.oracle.com/pls/apex/cetools/api/v1/products/?currencyCode=USD):
|
||||
|
||||
1. **`kb/pricing/oci-sku-catalog.yaml`** — 200+ SKUs across 20 categories
|
||||
(compute, storage, database, networking, observability, security, AI/ML,
|
||||
GenAI, etc.). Refresh: `python tools/refresh_sku_catalog.py --refresh`.
|
||||
2. **`kb/pricing/compute.yaml`** — shape-level estimation pricing
|
||||
(VM.Standard.E5.Flex hourly, monthly, etc.). Different abstraction from
|
||||
the SKU catalog — useful for SA estimation. Refresh:
|
||||
`python tools/refresh_sku_catalog.py --refresh-domain compute`.
|
||||
|
||||
**Pricing context that ISN'T a price** (billing models, BYOL rules, free
|
||||
tiers, service nuances, hyperscaler comparisons) lives in
|
||||
`kb/field-knowledge/pricing-knowledge.yaml`. That file is non-numeric where
|
||||
possible and does not need API refresh.
|
||||
|
||||
There are no other pricing files. The previous `kb/pricing/database.yaml`,
|
||||
`storage.yaml`, `networking.yaml`, etc. were removed on 2026-04-08 — their
|
||||
prices were drift-prone and 30-800% off the live API; their notes were
|
||||
migrated to `kb/field-knowledge/pricing-knowledge.yaml`.
|
||||
|
||||
## Linter
|
||||
|
||||
```bash
|
||||
python tools/kb_linter.py # all checks
|
||||
python tools/kb_linter.py --show-decay # confidence decay only
|
||||
python tools/kb_linter.py --check-tags # tag taxonomy only
|
||||
python tools/kb_linter.py --check-owners # domain owner assignments only
|
||||
```
|
||||
|
||||
The linter reports STALE / WARNING for files past their freshness threshold,
|
||||
unknown tags in field findings, and missing domain owners. Exit code is 1 if
|
||||
any issues are found.
|
||||
|
||||
## Review cadence
|
||||
|
||||
- **Field findings**: confidence decays automatically — see `config/kb-governance.yaml`
|
||||
- **Service cards**: review at least every 6 months, or when Oracle publishes a major update
|
||||
- **Patterns**: review at least once a year
|
||||
- **Pricing**: ideally every quarter — Oracle changes prices ~2x per year for major SKUs
|
||||
|
||||
## Thin directories
|
||||
|
||||
`compatibility/` and `field-findings/` currently hold a single file each.
|
||||
Both are expected to grow as more SAs contribute. If after 6 months they
|
||||
remain at 1 file, consider consolidating with a parent directory.
|
||||
@@ -9,12 +9,12 @@
|
||||
# STRONG MATCH: ≥2 service matches + ≥1 tag match
|
||||
# MODERATE MATCH: ≥1 service match + ≥2 tag matches
|
||||
#
|
||||
# Last refreshed: 2026-03-16
|
||||
# Last verified: 2026-03-16
|
||||
# Entry count: 123
|
||||
# To refresh: python tools/refresh_arch_catalog.py --whats-new
|
||||
# =============================================================================
|
||||
|
||||
last_refreshed: "2026-03-16"
|
||||
last_verified: "2026-03-16"
|
||||
source: "https://docs.oracle.com/en/solutions/oracle-architecture-center/"
|
||||
entry_count: 123
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
---
|
||||
last_verified: 2026-03-14
|
||||
description: Common customer objections about OCI and evidence-based responses.
|
||||
---
|
||||
|
||||
objections:
|
||||
- id: OBJ-001
|
||||
|
||||
295
kb/diagram/oracle-ref-measurements.md
Normal file
295
kb/diagram/oracle-ref-measurements.md
Normal file
@@ -0,0 +1,295 @@
|
||||
# Oracle Architecture Center Reference Diagram Measurements
|
||||
|
||||
Extracted from official Oracle .drawio source files (draw.io/28.0.4, Visio-exported).
|
||||
|
||||
Sources analyzed:
|
||||
1. Hub-and-Spoke DRG (hub-spoke-network-drg) - single-region, 3 VCNs, hub topology
|
||||
2. Essbase Cross-Region DR (cross-region-dr-essbase-oci) - dual-region, 3 ADs each, DR topology
|
||||
|
||||
Tool: draw.io 28.0.4 (Electron), exported from Visio (.vsdx)
|
||||
|
||||
---
|
||||
|
||||
## 1. Canvas / Page Settings
|
||||
|
||||
| Property | Hub-Spoke DRG | Essbase DR |
|
||||
|----------|--------------|------------|
|
||||
| pageWidth | 850 | 850 |
|
||||
| pageHeight | 1100 | 1100 |
|
||||
| gridSize | 10 | 10 |
|
||||
| Actual content W | 693 | 2339 |
|
||||
| Actual content H | 846 | 1154 |
|
||||
|
||||
---
|
||||
|
||||
## 2. Font Specifications
|
||||
|
||||
| Usage | Font Family | Font Size | Style |
|
||||
|-------|------------|-----------|-------|
|
||||
| Region/VCN/service labels | Oracle Sans | 16.93px (~17px) | Bold for region title |
|
||||
| Annotation text | Oracle Sans | 14.82px (~15px) | Regular |
|
||||
| Label box height | - | 20px | - |
|
||||
| Annotation box height | - | 17px | - |
|
||||
|
||||
---
|
||||
|
||||
## 3. Color Palette
|
||||
|
||||
| Element | Hex |
|
||||
|---------|-----|
|
||||
| OCI Region fill | #f5f4f2 |
|
||||
| OCI Region stroke | #9e9892 |
|
||||
| VCN / Subnet border (dashed) | #aa643b |
|
||||
| Connector lines / solid borders | #312d2a |
|
||||
| Service icon primary (teal) | #2d5967 |
|
||||
| Connector lines (Essbase) | #161513 |
|
||||
| AD fill (multi-AD diagrams) | #e4e1dd |
|
||||
| Background | #FFFFFF |
|
||||
| Accent brown | #ae562c |
|
||||
|
||||
---
|
||||
|
||||
## 4. Container Dimensions
|
||||
|
||||
### 4.1 OCI Region
|
||||
- Hub-Spoke: 456x845 at (236,0), fill=#f5f4f2, stroke=#9e9892
|
||||
- Essbase Left: 995x849 at (0,305)
|
||||
- Essbase Right: 1080x849 at (1258,304)
|
||||
- Pattern: Double-rendered (fill layer + stroke layer as separate shapes)
|
||||
|
||||
### 4.2 VCN
|
||||
- DMZ VCN (Hub-Spoke): 226x354 at (456,26)
|
||||
- Spoke VCN 1: 226x205 at (456,406)
|
||||
- Spoke VCN 2: 226x202 at (457,634)
|
||||
- Essbase left VCN: 894x766 at (30,355)
|
||||
- Essbase right VCN: 872x766 at (1328,354)
|
||||
- Style: strokeColor=#aa643b, strokeWidth=2, dashed=1, dashPattern=4.00 2.00
|
||||
|
||||
### 4.3 Subnet
|
||||
- Management Subnet: 176x134 at (498,76)
|
||||
- Services Subnet: 176x134 at (498,238)
|
||||
- Workload Subnet 1: 175x143 at (500,458)
|
||||
- Workload Subnet 2: 175x142 at (500,686)
|
||||
- Style: Same as VCN (strokeColor=#aa643b, strokeWidth=2, dashed)
|
||||
|
||||
### 4.4 Availability Domain (Essbase)
|
||||
- Width: 188, Height: 815
|
||||
- Positions: x=211, 425, 632 (left region), x=1508, 1724, 1930 (right region)
|
||||
- AD-to-AD gap: 18-28px (~25px avg)
|
||||
- Style: fill=#e4e1dd, stroke=#9e9892
|
||||
|
||||
### 4.5 On-Premises Box (Essbase)
|
||||
- 260x251 at (997,0) - centered between two regions
|
||||
- Style: fill=#f5f4f2, stroke=#9e9892
|
||||
|
||||
### 4.6 Workload Rows (Essbase)
|
||||
- Standard row: 807x111
|
||||
- Bottom row (expanded): 807x149
|
||||
- Y positions: 415, 552, 690, 828, 962
|
||||
- Row-to-row gap: 23-27px (~25px)
|
||||
|
||||
### 4.7 Compartment Boxes (Essbase)
|
||||
- 189x49 - placed at AD/row intersections
|
||||
|
||||
---
|
||||
|
||||
## 5. Icon Dimensions
|
||||
|
||||
### 5.1 Service Icons (VM, Bastion, Database, etc.)
|
||||
- 3-layer nesting: 63x63 outer > 61x61 middle > 60x60 inner
|
||||
- Standard service icon = 60px rendered in 63px box
|
||||
- Internal details: 13x13 grid cells, 43x13 bottom bar, 3x3 dots
|
||||
|
||||
### 5.2 Gateway Icons (IGW, NAT, SGW, DRG attachments)
|
||||
- 3-layer nesting: 42x42 outer > 41x41 middle > 40x40 inner
|
||||
- Central symbol: 29x26, internal detail: 22x29
|
||||
- Status indicators: 4x4 dots, 5x1 bars
|
||||
|
||||
### 5.3 OCI Toolkit Icons (Bastion-type)
|
||||
- 40x63 outer > 39x61 middle > 34x58 inner (portrait orientation)
|
||||
|
||||
### 5.4 Database/Storage Icons
|
||||
- 59x63 outer > 58x61 middle > inner symbol 39x26 + 21x21
|
||||
|
||||
### 5.5 External Icons (Internet, On-Premises)
|
||||
- Same 63x63 as service icons
|
||||
|
||||
---
|
||||
|
||||
## 6. Spacing Rules
|
||||
|
||||
### 6.1 Vertical Spacing
|
||||
| Measurement | Value |
|
||||
|-------------|-------|
|
||||
| Region label Y offset | 7px from region top |
|
||||
| VCN/Subnet label Y offset | 8px from container top |
|
||||
| VCN top to first subnet | 50px |
|
||||
| Subnet-to-subnet gap | 28px |
|
||||
| VCN-to-VCN gap | 26px |
|
||||
| Workload row gap | 23-27px (~25px) |
|
||||
| Gateway Y within VCN | 29px from VCN top |
|
||||
|
||||
### 6.2 Horizontal Spacing
|
||||
| Measurement | Value |
|
||||
|-------------|-------|
|
||||
| VCN to subnet left indent | 42-44px |
|
||||
| Service icon X within subnet | 80px from subnet left |
|
||||
| Gateway X from VCN left | 168px |
|
||||
| AD-to-AD gap | 18-28px (~25px) |
|
||||
| Inter-region gap (Essbase) | 263px |
|
||||
|
||||
### 6.3 Label Spacing
|
||||
| Measurement | Value |
|
||||
|-------------|-------|
|
||||
| Label box height | 20px (standard) |
|
||||
| Annotation box height | 17px |
|
||||
| Line-to-line spacing | 17px |
|
||||
|
||||
---
|
||||
|
||||
## 7. Connector Styles
|
||||
|
||||
Oracle Visio-exported .drawio files do NOT use draw.io native edges. Connectors are thin rectangles:
|
||||
- Horizontal: Wx1 rectangles, stroke=#312d2a
|
||||
- Vertical: 2xH or 1xH rectangles
|
||||
- Cross-region (Essbase): stroke=#161513
|
||||
- Examples:
|
||||
- Internet-to-Gateway: 350x1 at (80,153)
|
||||
- Mid-connections: 156x1 at (98,524)
|
||||
- DR replication: 549x1 at (391,1045)
|
||||
- Vertical link: 1x65 at (1128,365)
|
||||
|
||||
---
|
||||
|
||||
## 8. Border/Stroke Styles
|
||||
|
||||
| Element | strokeColor | strokeWidth | dashed | dashPattern |
|
||||
|---------|------------|-------------|--------|-------------|
|
||||
| Region | #9e9892 | 1 | No | - |
|
||||
| VCN | #aa643b | 2 | Yes | 4.00 2.00 |
|
||||
| Subnet | #aa643b | 2 | Yes | 4.00 2.00 |
|
||||
| AD | #9e9892 | 1 | No | - |
|
||||
| Solid grouping | #312d2a | 2 | No | - |
|
||||
| Connector | #312d2a/#161513 | 1 | No | - |
|
||||
|
||||
---
|
||||
|
||||
## 9. Double-Layer Container Rendering
|
||||
|
||||
Oracle renders each container as TWO overlapping shapes:
|
||||
1. Fill layer: fillColor=<color>, strokeColor=none
|
||||
2. Stroke layer: fillColor=none, strokeColor=<color>
|
||||
|
||||
This pattern applies to Region, VCN, Subnet, and AD containers.
|
||||
|
||||
---
|
||||
|
||||
## 10. Key Proportional Ratios
|
||||
|
||||
| Ratio | Value | Description |
|
||||
|-------|-------|-------------|
|
||||
| Gateway:Service icon | 42:63 = 0.67 | Gateways 2/3 size of service icons |
|
||||
| VCN:Subnet width | 226:176 = 1.28 | VCN ~28% wider than subnet |
|
||||
| VCN left padding | 42-44px | Subnet indent |
|
||||
| VCN top padding | 50px | To first subnet |
|
||||
| VCN bottom padding | ~22-26px | After last subnet |
|
||||
| Region aspect (hub-spoke) | 456:845 = 0.54 | Portrait |
|
||||
| AD aspect (multi-AD) | 188:815 = 0.23 | Very tall/narrow |
|
||||
| Workload row aspect | 807:111 = 7.27 | Very wide/short |
|
||||
|
||||
---
|
||||
|
||||
## 11. Recommended Calibration for oci_diagram_gen.py
|
||||
|
||||
```yaml
|
||||
region:
|
||||
min_width: 456
|
||||
min_height: 845
|
||||
fill: "#f5f4f2"
|
||||
stroke: "#9e9892"
|
||||
stroke_width: 1
|
||||
corner_radius: 0
|
||||
|
||||
vcn:
|
||||
min_width: 226
|
||||
typical_height_hub: 205
|
||||
typical_height_dmz: 354
|
||||
stroke: "#aa643b"
|
||||
stroke_width: 2
|
||||
dashed: true
|
||||
dash_pattern: "4 2"
|
||||
|
||||
subnet:
|
||||
width: 176
|
||||
typical_height: 134-143
|
||||
stroke: "#aa643b"
|
||||
stroke_width: 2
|
||||
dashed: true
|
||||
dash_pattern: "4 2"
|
||||
|
||||
availability_domain:
|
||||
width: 188
|
||||
height: 815
|
||||
fill: "#e4e1dd"
|
||||
stroke: "#9e9892"
|
||||
|
||||
service_icon:
|
||||
outer: 63
|
||||
rendered: 60
|
||||
|
||||
gateway_icon:
|
||||
outer: 42
|
||||
rendered: 40
|
||||
inner_symbol: 29x26
|
||||
|
||||
spacing:
|
||||
vcn_to_vcn_gap: 26
|
||||
subnet_to_subnet_gap: 28
|
||||
vcn_top_to_first_subnet: 50
|
||||
vcn_left_to_subnet: 42
|
||||
subnet_to_service_icon: 80
|
||||
gateway_x_from_vcn_left: 168
|
||||
gateway_y_from_vcn_top: 29
|
||||
label_y_offset: 8
|
||||
region_label_y: 7
|
||||
workload_row_gap: 25
|
||||
ad_to_ad_gap: 25
|
||||
inter_region_gap: 263
|
||||
|
||||
fonts:
|
||||
family: "Oracle Sans"
|
||||
label_size: 17
|
||||
annotation_size: 15
|
||||
label_box_height: 20
|
||||
annotation_box_height: 17
|
||||
|
||||
colors:
|
||||
region_fill: "#f5f4f2"
|
||||
region_stroke: "#9e9892"
|
||||
vcn_stroke: "#aa643b"
|
||||
subnet_stroke: "#aa643b"
|
||||
ad_fill: "#e4e1dd"
|
||||
icon_primary: "#2d5967"
|
||||
text_dark: "#312d2a"
|
||||
connector: "#312d2a"
|
||||
background: "#FFFFFF"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. Layout Patterns
|
||||
|
||||
### Single-Region Hub-Spoke
|
||||
- VCNs stacked vertically
|
||||
- External icons (Internet, On-Prem) at far left
|
||||
- Gateways between external and VCN
|
||||
- DRG centered with route table
|
||||
- Service icons right-aligned within subnets
|
||||
|
||||
### Dual-Region DR
|
||||
- Regions side by side horizontally
|
||||
- On-Premises box centered above/between regions
|
||||
- ADs as vertical columns within each region
|
||||
- Workload tiers as horizontal rows crossing all ADs
|
||||
- Compartment boxes at AD-row intersections
|
||||
- DR arrows as horizontal lines between matching rows
|
||||
@@ -47,8 +47,12 @@ findings:
|
||||
|
||||
- id: "FF-202603-008"
|
||||
date: "2026-03-14"
|
||||
reported_by: "Diego Cabrera"
|
||||
client: "Vector Search Customer"
|
||||
contributor:
|
||||
name: "Diego Cabrera"
|
||||
team: "Field Architecture"
|
||||
client: "Vector Search Customer"
|
||||
context: "AI Vector Search engagement"
|
||||
confidence: "validated"
|
||||
product: "ADB-S"
|
||||
version: "23ai"
|
||||
severity: "HIGH"
|
||||
|
||||
419
kb/field-knowledge/pricing-knowledge.yaml
Normal file
419
kb/field-knowledge/pricing-knowledge.yaml
Normal file
@@ -0,0 +1,419 @@
|
||||
---
|
||||
last_verified: 2026-04-08
|
||||
source: Migrated from former kb/pricing/<domain>.yaml files (removed 2026-04-08).
|
||||
Stable, non-numeric pricing knowledge that does not need API refresh.
|
||||
All actual price numbers live in kb/pricing/oci-sku-catalog.yaml (auto-refreshed).
|
||||
description: Pricing context, billing models, free tiers, BYOL rules, and
|
||||
cross-service estimation knowledge for the OCI Deal Accelerator.
|
||||
---
|
||||
|
||||
# =============================================================================
|
||||
# OCI Pricing Knowledge
|
||||
# =============================================================================
|
||||
#
|
||||
# This file is the human-readable companion to kb/pricing/oci-sku-catalog.yaml.
|
||||
# The catalog has live SKU prices (auto-refreshed). This file has the *context*
|
||||
# a Solutions Architect needs to estimate accurately:
|
||||
# - Pricing models and when to use each
|
||||
# - BYOL rules and savings
|
||||
# - Free-tier rules per service
|
||||
# - Service-specific billing nuances
|
||||
# - Cost comparison framing vs hyperscalers
|
||||
#
|
||||
# This file is intentionally non-numeric where possible. Specific prices that
|
||||
# change should NOT be added here — add them to the SKU catalog instead.
|
||||
# Where a percentage or range is unavoidable (e.g. "BYOL ~50% off"), prefer
|
||||
# stable rules of thumb over exact figures.
|
||||
# =============================================================================
|
||||
|
||||
# ── PRICING MODELS ────────────────────────────────────────────────
|
||||
|
||||
pricing_models:
|
||||
payg:
|
||||
name: Pay As You Go
|
||||
commitment: none
|
||||
billing: Per second (compute), per hour (database), per month (storage)
|
||||
when_to_use:
|
||||
- Variable / unpredictable workloads
|
||||
- Short-term projects
|
||||
- Dev / test environments
|
||||
- Initial cloud adoption (before committing)
|
||||
|
||||
monthly_flex:
|
||||
name: Monthly Flex (Universal Credits)
|
||||
commitment: Minimum $1,000/month or custom commitment
|
||||
billing: Committed credits consumed by usage
|
||||
discount_tiers:
|
||||
- spend_band: $1K-$10K/month
|
||||
approx_discount: 5-10%
|
||||
- spend_band: $10K-$50K/month
|
||||
approx_discount: 10-20%
|
||||
- spend_band: $50K+/month
|
||||
approx_discount: 20-30% (negotiated)
|
||||
when_to_use:
|
||||
- Steady-state production workloads
|
||||
- Known baseline consumption
|
||||
- Multiple services across OCI
|
||||
|
||||
annual_flex:
|
||||
name: Annual Flex (Committed)
|
||||
commitment: 1-year or 3-year
|
||||
discount: Deeper than Monthly Flex
|
||||
when_to_use:
|
||||
- Established production workloads with predictable spend
|
||||
- Organizations committed to OCI long-term
|
||||
|
||||
byol:
|
||||
name: Bring Your Own License
|
||||
approx_savings: ~50% on database ECPU/OCPU costs
|
||||
eligible:
|
||||
- Oracle Database Enterprise Edition
|
||||
- Oracle Database Standard Edition 2
|
||||
- Oracle WebLogic
|
||||
- Oracle Java SE
|
||||
conversion: 1 processor license = 2 OCPUs (or 8 ECPUs)
|
||||
when_to_use:
|
||||
- Existing Oracle on-prem licenses with active support
|
||||
- Licenses not being used elsewhere
|
||||
when_not_to_use:
|
||||
- No existing licenses
|
||||
- Licenses still needed for on-prem during migration
|
||||
- Standard Edition workloads on ADB (ADB requires EE)
|
||||
|
||||
reserved_capacity:
|
||||
name: Reserved Capacity
|
||||
commitment: 1-year or 3-year for specific shapes
|
||||
approx_discount:
|
||||
one_year: ~35% off on-demand
|
||||
three_year: ~55% off on-demand
|
||||
when_to_use:
|
||||
- Known compute shapes running 24/7
|
||||
- Predictable database capacity
|
||||
notes: Shape-specific, less flexible than Universal Credits
|
||||
|
||||
# ── ESTIMATION APPROACH ──────────────────────────────────────────
|
||||
|
||||
estimation_approach:
|
||||
steps:
|
||||
- Calculate PAYG cost first (baseline)
|
||||
- Apply BYOL if customer has eligible licenses
|
||||
- Show savings with Monthly Flex / Annual Flex for steady-state
|
||||
- Compare total annual cost vs current on-prem spending
|
||||
- Include migration costs in year 1
|
||||
assumptions_to_state:
|
||||
- Hours per month (730 for 24/7)
|
||||
- Auto-scaling hours per day (estimate)
|
||||
- Data transfer volumes (egress in particular)
|
||||
- Backup retention policy
|
||||
- Support tier (Premier vs Standard)
|
||||
|
||||
# ── DATABASE KNOWLEDGE ──────────────────────────────────────────
|
||||
|
||||
database:
|
||||
billing_unit_change:
|
||||
fact: ADB and most modern Oracle Database services bill in ECPUs, not OCPUs.
|
||||
rule_of_thumb: 1 OCPU ≈ 4 ECPUs for sizing conversion.
|
||||
note: When reading old datasheets or RFP documents, normalize to ECPU before quoting.
|
||||
|
||||
autonomous_database_serverless:
|
||||
auto_scaling: Billed per ECPU-second for additional ECPUs above base. Same hourly rate as base ECPUs.
|
||||
adg_standby: Standby ECPU cost at the same rate as primary. Storage shared (no extra storage charge).
|
||||
backup: Automated backups included in storage cost. Manual backups use Object Storage rates.
|
||||
sweet_spot: 4-32 ECPUs with auto-scaling. Below 4, consider Always Free. Above 128, consider ADB-D or ExaCS.
|
||||
|
||||
autonomous_database_dedicated:
|
||||
x11m_elastic_model:
|
||||
description: |
|
||||
X11M is the current-generation Exadata infrastructure for ADB-D and
|
||||
ExaCS (announced 2025). It uses elastic scaling instead of fixed
|
||||
quarter / half / full racks.
|
||||
configuration:
|
||||
min_db_servers: 2
|
||||
min_storage_servers: 3
|
||||
max_db_servers: 32
|
||||
max_storage_servers: 64
|
||||
key_changes_vs_x9m:
|
||||
- No fixed rack shapes — elastic scale in / out by server
|
||||
- Hard minimum: 2 DB + 3 storage servers (cannot provision less)
|
||||
- Per-second ECPU billing (was per-hour in older generations)
|
||||
- Improved compute, storage density, RDMA throughput
|
||||
pricing_caveat: |
|
||||
Per-server line items exist in the OCI price list ('Database Server -
|
||||
X11M', 'Storage Server - X11M') but the dollar amounts are not visible
|
||||
in the public API. For estimation, use X9M quarter rack as a proxy
|
||||
and confirm final pricing with the Oracle PDM / sales team.
|
||||
legacy_x9m_model:
|
||||
shapes:
|
||||
- quarter_rack
|
||||
- half_rack
|
||||
- full_rack
|
||||
note: Still available in some regions; new deployments default to X11M.
|
||||
|
||||
dbcs_editions:
|
||||
SE: Standard Edition 2
|
||||
EE: Enterprise Edition (base)
|
||||
EE_HP: Enterprise Edition - High Performance (partitioning, advanced compression, etc.)
|
||||
EE_EP: Enterprise Edition - Extreme Performance (RAC, Active Data Guard, In-Memory)
|
||||
note: Backup storage is charged separately at Object Storage rates.
|
||||
|
||||
exacs_gotchas:
|
||||
- Infrastructure cost is fixed regardless of ECPU utilization on X9M (rack-based).
|
||||
- X11M elastic model bills by server, not by rack — scale in / out as needed.
|
||||
- Provisioning takes 4-8 hours.
|
||||
- Billing starts only at AVAILABLE state.
|
||||
- For X11M, the public API does not expose infrastructure-rate dollar amounts — confirm with PDM.
|
||||
|
||||
exadata_cloud_at_customer:
|
||||
note: Exadata infrastructure deployed in the customer datacenter, managed by Oracle.
|
||||
same_ecpu_pricing_as: ExaCS Dedicated
|
||||
|
||||
database_migration_service:
|
||||
free_period: First 183 days of an active migration are free.
|
||||
|
||||
backup_recovery:
|
||||
autonomous_recovery_service: Per-GB protected per month, virtualized.
|
||||
zdlra: Zero Data Loss variant — same model, slightly higher rate.
|
||||
|
||||
cost_comparison_vs_hyperscalers:
|
||||
when_pitching_vs_aws_rds_or_azure_sqlmi:
|
||||
include_in_comparison:
|
||||
- OCI inbound data transfer is free
|
||||
- OCI egress to internet is dramatically cheaper (~80% less than AWS after 10TB free)
|
||||
- OCI BYOL discount is deeper than AWS BYOL
|
||||
- ADB-S includes patching, tuning, indexing — RDS does not
|
||||
- ADB now bills in ECPU (not OCPU) — 1 ECPU is a fraction of an OCPU
|
||||
- Network LB is free per-hour on OCI
|
||||
|
||||
# ── NETWORKING KNOWLEDGE ────────────────────────────────────────
|
||||
|
||||
networking:
|
||||
data_transfer:
|
||||
ingress: Free (all sources)
|
||||
egress_internet:
|
||||
free_tier: First 10 TB / month is free
|
||||
billing_after: Per-GB charge applies beyond free tier
|
||||
inter_region: Per-GB charge (low)
|
||||
fastconnect: Free in both directions (ingress AND egress)
|
||||
competitive_advantage: |
|
||||
OCI is dramatically cheaper than hyperscalers for data transfer:
|
||||
- AWS: $0.09 / GB egress (OCI is ~10x cheaper after 10 TB free)
|
||||
- Azure: $0.087 / GB egress
|
||||
- GCP: $0.12 / GB egress
|
||||
- OCI FastConnect egress is FREE (AWS DirectConnect charges per GB)
|
||||
This is one of the strongest cost arguments when migrating data-intensive
|
||||
workloads from AWS / Azure / GCP.
|
||||
|
||||
fastconnect:
|
||||
note: Private dedicated connectivity. No data transfer charges.
|
||||
port_speeds_available_in_api: [1, 2, 5, 10, 40, 100, 400] # Gbps
|
||||
note_400gbps: 400 Gbps option is available; check oci-sku-catalog.yaml for current SKUs.
|
||||
|
||||
network_load_balancer:
|
||||
cost_model: No per-hour charge (Layer 4). Data processing fees apply.
|
||||
|
||||
flexible_load_balancer:
|
||||
cost_model: Base instance hourly + bandwidth per Mbps-hour. See oci-sku-catalog.yaml.
|
||||
|
||||
vpn_connect:
|
||||
cost_model: No additional charge for IPSec VPN tunnels. Included with DRG.
|
||||
|
||||
dns:
|
||||
free_tier: 1 million queries / month at no cost.
|
||||
|
||||
waf:
|
||||
cost_model: Pricing based on requests processed. See oci-sku-catalog.yaml.
|
||||
|
||||
# ── STORAGE KNOWLEDGE ───────────────────────────────────────────
|
||||
|
||||
storage:
|
||||
block_volume:
|
||||
tier_model: |
|
||||
OCI block volume tiers are configured via Volume Performance Units (VPU):
|
||||
- Lower Cost: 0 VPU
|
||||
- Balanced: 10 VPU (default)
|
||||
- Higher Performance: 20 VPU
|
||||
- Ultra High Performance (UHP): 30-120 VPU
|
||||
The base storage SKU is the same across tiers; the difference is the
|
||||
VPU multiplier on top. See oci-sku-catalog.yaml for the base storage
|
||||
SKU and the VPU SKU.
|
||||
boot_volume_free_tier: First 200 GB included with each compute instance.
|
||||
backup_billing: Block volume backups have their own per-GB-month rate (lower than primary).
|
||||
|
||||
object_storage:
|
||||
tiers:
|
||||
standard: General-purpose, immediate access.
|
||||
infrequent_access: Lower per-GB cost; retrieval fee applies.
|
||||
archive: Lowest per-GB cost; standard retrieval is ~1 hour.
|
||||
free_tier: 10 GB storage + 50,000 requests / month always free.
|
||||
request_pricing: Separate per-10k-PUT and per-10k-GET charges.
|
||||
|
||||
file_storage:
|
||||
note: Per-GB-month, higher rate than block volume.
|
||||
high_performance_mount_target: Available for high-throughput workloads.
|
||||
|
||||
# ── OBSERVABILITY & MANAGEMENT KNOWLEDGE ────────────────────────
|
||||
|
||||
observability:
|
||||
free_services:
|
||||
- Cloud Guard (tenancy threat detection)
|
||||
- Security Zones (compartment policy enforcement)
|
||||
- Vulnerability Scanning (host + container image)
|
||||
- Certificates (TLS certificate management)
|
||||
- Bastion (managed SSH / RDP bastion)
|
||||
- Vault (software keys; HSM is paid)
|
||||
- OS Management Hub
|
||||
- Java Management Service
|
||||
- Autonomous Linux
|
||||
- Resource Analytics
|
||||
- Events service
|
||||
- DevOps pipeline execution (compute / storage billed separately)
|
||||
- Cluster management for OKE basic clusters
|
||||
|
||||
free_tiers:
|
||||
monitoring:
|
||||
ingestion: 500 million datapoints / month
|
||||
retrieval: 1 billion datapoints / month
|
||||
logging:
|
||||
free_per_month: 10 GB
|
||||
queue:
|
||||
free_per_month: 1 million requests
|
||||
functions:
|
||||
invocations: 2 million / month
|
||||
memory: 400,000 GB-seconds / month
|
||||
notifications:
|
||||
deliveries: 1 million / month
|
||||
emails: 1,000 / month
|
||||
|
||||
ops_insights:
|
||||
note: Basic and Autonomous tiers are free. Cloud-external (e.g. on-prem databases) is paid per OCPU-hour.
|
||||
|
||||
log_analytics:
|
||||
unit: 1 storage unit = 300 GB.
|
||||
|
||||
full_stack_dr:
|
||||
note: Orchestrates DR failover across compute, database, and networking. Billed per ECPU / OCPU hour.
|
||||
|
||||
# ── COMPUTE / CONTAINERS / SERVERLESS KNOWLEDGE ────────────────
|
||||
|
||||
compute_containers_serverless:
|
||||
oke:
|
||||
basic_cluster: Cluster management is free (control plane).
|
||||
enhanced_cluster: Per-cluster hourly charge — adds virtual nodes, workload identity, etc.
|
||||
worker_nodes: Billed at standard compute shape rates (see kb/pricing/compute.yaml).
|
||||
virtual_nodes: Additional per-pod pricing on enhanced clusters.
|
||||
|
||||
container_instances:
|
||||
billing: Billed at compute rates (OCPU / hour + GB memory / hour). No additional service charge.
|
||||
shapes_available: [A1 (Arm), E3 (AMD), E4 (AMD), E5 (AMD), E6 (AMD)]
|
||||
|
||||
functions:
|
||||
free_tier_strength: Very generous — most event-driven workloads stay in the free tier.
|
||||
|
||||
batch:
|
||||
billing: Pay-as-you-go compute pricing, no additional service charge.
|
||||
|
||||
# ── INTEGRATION & MIDDLEWARE KNOWLEDGE ─────────────────────────
|
||||
|
||||
integration:
|
||||
integration_cloud:
|
||||
editions: [Standard, Enterprise]
|
||||
billing_unit: Per 5,000 messages / hour band
|
||||
|
||||
api_management:
|
||||
note: Per-API-call pricing is very low; most use cases trivially below $1 / million calls.
|
||||
|
||||
streaming:
|
||||
note: Kafka-compatible. Billed per GB stored per hour + per GB transferred.
|
||||
|
||||
queue:
|
||||
free_tier_strength: 1 million requests / month free, very cost-effective for decoupling.
|
||||
|
||||
goldengate:
|
||||
billing: OCPU-hour. BYOL available.
|
||||
use_case: Real-time data integration and replication.
|
||||
|
||||
soa_suite:
|
||||
note: For legacy SOA workload migration. OCPU-hour billing.
|
||||
|
||||
# ── DEVELOPER SERVICES KNOWLEDGE ───────────────────────────────
|
||||
|
||||
developer:
|
||||
apex:
|
||||
free_tier: Yes — APEX free tier available for low-code development.
|
||||
visual_builder:
|
||||
note: Low-code app builder with included storage.
|
||||
devops:
|
||||
free: Pipeline execution itself is free; compute / memory billed separately.
|
||||
blockchain:
|
||||
note: OCPU-hour billing; storage charged separately.
|
||||
iot:
|
||||
billing_unit: ECPU-hour.
|
||||
media_flow:
|
||||
billing: Per-minute, varies by codec, resolution, and fps.
|
||||
media_streams:
|
||||
billing: Per-GB packaged.
|
||||
|
||||
# ── AI / ML KNOWLEDGE ──────────────────────────────────────────
|
||||
|
||||
ai_ml:
|
||||
generative_ai_vendors_available:
|
||||
- Cohere (Command, Embed)
|
||||
- Meta Llama
|
||||
- xAI Grok
|
||||
- Google Gemini
|
||||
generative_ai_billing_unit: Per 10K transactions or per 1M tokens (varies by vendor).
|
||||
generative_ai_agents:
|
||||
extra_costs: Plus storage and ingestion fees for agent knowledge bases.
|
||||
|
||||
data_science:
|
||||
notebook_sessions: Billed at compute shape rates (OCPU / hour + GB memory / hour + GPU options).
|
||||
jobs: Same compute pricing as notebook sessions.
|
||||
model_deployment: Compute + networking + storage combined pricing.
|
||||
model_catalog_storage: Object Storage rates.
|
||||
|
||||
anomaly_detection:
|
||||
free_tier: Up to 100M data points / month per region.
|
||||
|
||||
document_understanding:
|
||||
note: OCR billed per 1K transactions; custom training billed per training hour.
|
||||
|
||||
language_services:
|
||||
note: Pretrained per-transaction billing; custom training available at additional cost.
|
||||
|
||||
vision:
|
||||
note: Per-1K image analysis billing; custom training per hour.
|
||||
|
||||
speech:
|
||||
note: Per-transcription-hour billing.
|
||||
|
||||
digital_assistant:
|
||||
note: Per-request billing with a minimum throughput floor.
|
||||
|
||||
# ── SECURITY KNOWLEDGE ─────────────────────────────────────────
|
||||
|
||||
security:
|
||||
free_services:
|
||||
- Cloud Guard
|
||||
- Security Zones
|
||||
- Vulnerability Scanning
|
||||
- Certificates
|
||||
- Bastion
|
||||
- Vault (software keys only — HSM keys are paid)
|
||||
paid_services:
|
||||
- Access Governance (per workforce / consumer user / month)
|
||||
- Network Firewall (instance hours + data processed)
|
||||
- Data Safe (per target / month + audit records)
|
||||
- Vault (HSM-backed keys)
|
||||
|
||||
# ── HYBRID / EDGE KNOWLEDGE ────────────────────────────────────
|
||||
|
||||
hybrid:
|
||||
vmware_solution:
|
||||
note: Bare-metal nodes (BM.Standard2.12, BM.Standard3.16, BM.Standard.E4.32, BM.Standard.E5.48). Hourly to 3-year commitment ranges.
|
||||
hcx_enterprise: Available for cross-cloud migration from on-prem vSphere; 1-month minimum commitment.
|
||||
compute_cloud_at_customer:
|
||||
note: OCI compute, storage, and load balancer in customer datacenter. E6 shapes available.
|
||||
managed_mac:
|
||||
note: Apple Mac instances (M2 Pro, M4 Pro) for iOS / macOS build pipelines.
|
||||
roving_edge:
|
||||
note: Portable compute / GPU / storage devices for edge and disconnected scenarios. Per-device-day billing.
|
||||
@@ -28,7 +28,7 @@ variants:
|
||||
name: "Same-Region Autonomous Data Guard Standby"
|
||||
topology: "Primary + Standby in same region via Autonomous Data Guard"
|
||||
rpo: "0 (synchronous replication)"
|
||||
rto: "< 30 seconds (automatic switchover)"
|
||||
rto: "~2 minutes (automatic switchover)"
|
||||
use_when:
|
||||
- "Zero RPO mandatory"
|
||||
- "Protection against full AD or FD failure"
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
---
|
||||
last_verified: 2026-03-18
|
||||
pattern:
|
||||
id: ecal-artefacts-catalog
|
||||
name: "ECAL 3.1 Artefacts Catalog"
|
||||
category: governance
|
||||
---
|
||||
|
||||
description: >
|
||||
Complete catalog of ECAL 3.1 artefacts across all 9 steps.
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI AI and Machine Learning service pricing.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── OCI Generative AI ─────────────────────────────────────────────
|
||||
|
||||
generative_ai:
|
||||
cohere_models:
|
||||
per_10k_transactions: 0.0001 - 0.0003
|
||||
notes: "Command, Embed models"
|
||||
meta_llama:
|
||||
per_10k_transactions: 0.0001 - 0.0004
|
||||
xai_grok:
|
||||
per_1m_tokens_range: "$0.00015 – $0.0018"
|
||||
google_gemini:
|
||||
per_1m_tokens_range: "$0.000075 – $0.0006"
|
||||
|
||||
generative_ai_agents:
|
||||
per_10k_transactions: 0.0001
|
||||
notes: "Plus storage and ingestion fees"
|
||||
|
||||
# ── Anomaly Detection ─────────────────────────────────────────────
|
||||
|
||||
anomaly_detection:
|
||||
training: "Free up to 100M data points/month per region"
|
||||
|
||||
# ── Data Science ───────────────────────────────────────────────────
|
||||
|
||||
data_science:
|
||||
notebook_sessions:
|
||||
notes: "Billed at compute shape rates (OCPU/hour + GB memory/hour + GPU options)"
|
||||
jobs:
|
||||
notes: "Same compute pricing as notebook sessions"
|
||||
model_deployment:
|
||||
notes: "Compute + networking + storage combined pricing"
|
||||
model_catalog_storage:
|
||||
notes: "Object Storage rates"
|
||||
|
||||
# ── Document Understanding ─────────────────────────────────────────
|
||||
|
||||
document_understanding:
|
||||
training_per_hour: 0.50 - 1.00
|
||||
ocr_per_1k_transactions: 0.025 - 0.050
|
||||
|
||||
# ── Language Services ──────────────────────────────────────────────
|
||||
|
||||
language:
|
||||
pretrained_per_transaction: 0.0001 - 0.0003
|
||||
custom_training: "Available at additional cost"
|
||||
|
||||
# ── Vision ─────────────────────────────────────────────────────────
|
||||
|
||||
vision:
|
||||
image_analysis_per_1k: 0.0001 - 0.0003
|
||||
custom_training_per_hour: 0.50 - 1.00
|
||||
|
||||
# ── Speech ─────────────────────────────────────────────────────────
|
||||
|
||||
speech:
|
||||
per_transcription_hour: 0.0025 - 0.005
|
||||
|
||||
# ── Digital Assistant ──────────────────────────────────────────────
|
||||
|
||||
digital_assistant:
|
||||
per_request: 0.009
|
||||
minimum: "250 requests/hour"
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Analytics and BI pricing.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── Oracle Analytics Cloud ─────────────────────────────────────────
|
||||
|
||||
oracle_analytics_cloud:
|
||||
per_user_month:
|
||||
professional: 0.99
|
||||
enterprise: 2.00
|
||||
ocpu_based:
|
||||
notes: "Also available as OCPU-based pricing for embedded/API use"
|
||||
|
||||
# ── Essbase ────────────────────────────────────────────────────────
|
||||
|
||||
essbase:
|
||||
ocpu_per_hour: 0.0252
|
||||
|
||||
# ── Data Lake / Big Data ──────────────────────────────────────────
|
||||
|
||||
ai_data_platform:
|
||||
notes: "Pricing by AI Data Platform unit"
|
||||
|
||||
big_data_service_oracle:
|
||||
ocpu_per_hour: 0.0252
|
||||
notes: "Oracle distribution, includes Spark SQL compute"
|
||||
|
||||
big_data_service_cloudera:
|
||||
ocpu_per_hour: 0.0168 - 0.0336
|
||||
|
||||
data_flow:
|
||||
ocpu_usage: "Free"
|
||||
notes: "Apache Spark, no charge for OCPU usage"
|
||||
@@ -1,191 +1,160 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Compute pricing for estimation purposes.
|
||||
Prices are approximate and subject to change. Always verify with
|
||||
OCI pricing calculator for final quotes.
|
||||
last_verified: '2026-04-08'
|
||||
source: https://apexapps.oracle.com/pls/apex/cetools/api/v1/products/
|
||||
description: OCI Compute pricing for estimation purposes. Auto-refreshed from the
|
||||
Oracle public pricing API by tools/refresh_sku_catalog.py --refresh-domain compute.
|
||||
GPU shapes, secure desktops, estimation_helpers, and discounts are NOT auto-refreshed.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── Virtual Machine Instances ──────────────────────────────────────
|
||||
|
||||
flexible_shapes:
|
||||
VM.Standard.E6.Flex:
|
||||
ocpu_per_hour: 0.0168
|
||||
memory_per_gb_hour: 0.0011
|
||||
ocpu_per_hour: 0.03
|
||||
memory_per_gb_hour: 0.002
|
||||
monthly_730h:
|
||||
ocpu: 12.26
|
||||
memory_per_gb: 0.80
|
||||
notes: "AMD EPYC (latest gen), best price/performance for general workloads"
|
||||
|
||||
ocpu: 21.9
|
||||
memory_per_gb: 1.46
|
||||
notes: AMD EPYC (latest gen), best price/performance for general workloads
|
||||
VM.Standard.E5.Flex:
|
||||
ocpu_per_hour: 0.0210
|
||||
memory_per_gb_hour: 0.0014
|
||||
ocpu_per_hour: 0.03
|
||||
memory_per_gb_hour: 0.002
|
||||
monthly_730h:
|
||||
ocpu: 15.33
|
||||
memory_per_gb: 1.02
|
||||
notes: "AMD EPYC, general-purpose workloads"
|
||||
|
||||
ocpu: 21.9
|
||||
memory_per_gb: 1.46
|
||||
notes: AMD EPYC, general-purpose workloads
|
||||
VM.Standard.E4.Flex:
|
||||
ocpu_per_hour: 0.0252
|
||||
memory_per_gb_hour: 0.0017
|
||||
ocpu_per_hour: 0.025
|
||||
memory_per_gb_hour: 0.0015
|
||||
monthly_730h:
|
||||
ocpu: 18.40
|
||||
memory_per_gb: 1.24
|
||||
notes: "AMD EPYC (previous gen)"
|
||||
|
||||
ocpu: 18.25
|
||||
memory_per_gb: 1.09
|
||||
notes: AMD EPYC (previous gen)
|
||||
VM.Standard.E3.Flex:
|
||||
ocpu_per_hour: 0.0252
|
||||
memory_per_gb_hour: 0.0017
|
||||
ocpu_per_hour: 0.025
|
||||
memory_per_gb_hour: 0.0015
|
||||
monthly_730h:
|
||||
ocpu: 18.40
|
||||
memory_per_gb: 1.24
|
||||
notes: "AMD EPYC (older gen)"
|
||||
|
||||
ocpu: 18.25
|
||||
memory_per_gb: 1.09
|
||||
notes: AMD EPYC (older gen)
|
||||
VM.Standard3.Flex:
|
||||
ocpu_per_hour: 0.0336
|
||||
memory_per_gb_hour: 0.0022
|
||||
monthly_730h:
|
||||
ocpu: 24.53
|
||||
memory_per_gb: 1.61
|
||||
notes: "Intel Xeon, for Intel-optimized workloads"
|
||||
|
||||
notes: Intel Xeon, for Intel-optimized workloads
|
||||
VM.Standard.A2.Flex:
|
||||
ocpu_per_hour: 0.0254
|
||||
memory_per_gb_hour: 0.0017
|
||||
ocpu_per_hour: 0.014
|
||||
memory_per_gb_hour: 0.002
|
||||
monthly_730h:
|
||||
ocpu: 18.54
|
||||
memory_per_gb: 1.24
|
||||
notes: "Ampere Arm (latest A2), best cost for Arm-compatible workloads"
|
||||
|
||||
ocpu: 10.22
|
||||
memory_per_gb: 1.46
|
||||
notes: Ampere Arm (latest A2), best cost for Arm-compatible workloads
|
||||
VM.Standard.A1.Flex:
|
||||
ocpu_per_hour: 0.0127
|
||||
memory_per_gb_hour: 0.0008
|
||||
monthly_730h:
|
||||
ocpu: 9.27
|
||||
memory_per_gb: 0.58
|
||||
free_tier: "3,000 OCPU-hours + 18,000 GB-hours per month"
|
||||
notes: "Ampere Arm A1, eligible for Always Free tier"
|
||||
|
||||
free_tier: 3,000 OCPU-hours + 18,000 GB-hours per month
|
||||
notes: Ampere Arm A1, eligible for Always Free tier
|
||||
VM.Standard.x86.Generic:
|
||||
ocpu_per_hour: 0.0252
|
||||
memory_per_gb_hour: 0.0017
|
||||
notes: "Generic x86 pricing when specific shape not yet selected"
|
||||
|
||||
notes: Generic x86 pricing when specific shape not yet selected
|
||||
VM.Optimized3.Flex:
|
||||
ocpu_per_hour: 0.0504
|
||||
memory_per_gb_hour: 0.0034
|
||||
ocpu_per_hour: 0.054
|
||||
memory_per_gb_hour: 0.0015
|
||||
monthly_730h:
|
||||
ocpu: 36.79
|
||||
memory_per_gb: 2.48
|
||||
notes: "Highest single-thread performance"
|
||||
|
||||
# ── Bare Metal Instances ───────────────────────────────────────────
|
||||
|
||||
ocpu: 39.42
|
||||
memory_per_gb: 1.09
|
||||
notes: Highest single-thread performance
|
||||
bare_metal_shapes:
|
||||
BM.Standard.E5:
|
||||
ocpu_per_hour: 0.0168
|
||||
notes: "AMD EPYC bare metal"
|
||||
ocpu_per_hour: 0.03
|
||||
notes: AMD EPYC bare metal
|
||||
BM.Standard.E4:
|
||||
ocpu_per_hour: 0.0210
|
||||
notes: "AMD EPYC bare metal (previous gen)"
|
||||
ocpu_per_hour: 0.025
|
||||
notes: AMD EPYC bare metal (previous gen)
|
||||
BM.Standard.E3:
|
||||
ocpu_per_hour: 0.0420
|
||||
notes: "AMD EPYC bare metal (older gen)"
|
||||
ocpu_per_hour: 0.025
|
||||
notes: AMD EPYC bare metal (older gen)
|
||||
BM.Standard3:
|
||||
ocpu_per_hour: 0.0504
|
||||
notes: "Intel Xeon bare metal"
|
||||
notes: Intel Xeon bare metal
|
||||
BM.Standard.A1:
|
||||
ocpu_per_hour: 0.0127
|
||||
notes: "Ampere Arm bare metal"
|
||||
notes: Ampere Arm bare metal
|
||||
BM.Standard.x9:
|
||||
ocpu_per_hour: 0.0672
|
||||
notes: "Intel Xeon x9 bare metal"
|
||||
|
||||
# ── GPU Accelerated Compute ────────────────────────────────────────
|
||||
|
||||
ocpu_per_hour: 0.04
|
||||
notes: Intel Xeon x9 bare metal
|
||||
gpu_shapes:
|
||||
# NVIDIA Blackwell (latest)
|
||||
BM.GPU.B300:
|
||||
per_gpu_hour: 26.88
|
||||
gpu_count: 8
|
||||
gpu_model: "NVIDIA B300"
|
||||
notes: "Blackwell latest, HPC/AI training"
|
||||
gpu_model: NVIDIA B300
|
||||
notes: Blackwell latest, HPC/AI training
|
||||
BM.GPU.B200:
|
||||
per_gpu_hour: 20.16
|
||||
gpu_count: 8
|
||||
gpu_model: "NVIDIA B200"
|
||||
notes: "Blackwell, large-scale training"
|
||||
|
||||
# NVIDIA Hopper
|
||||
gpu_model: NVIDIA B200
|
||||
notes: Blackwell, large-scale training
|
||||
BM.GPU.H200:
|
||||
per_gpu_hour: 18.54
|
||||
gpu_count: 8
|
||||
gpu_model: "NVIDIA H200"
|
||||
notes: "Hopper H200, large model training"
|
||||
gpu_model: NVIDIA H200
|
||||
notes: Hopper H200, large model training
|
||||
BM.GPU.H100:
|
||||
per_gpu_hour: 12.96
|
||||
gpu_count: 8
|
||||
gpu_model: "NVIDIA H100"
|
||||
notes: "Hopper H100, training workloads"
|
||||
|
||||
# NVIDIA Ampere / Ada
|
||||
gpu_model: NVIDIA H100
|
||||
notes: Hopper H100, training workloads
|
||||
BM.GPU.A100:
|
||||
per_gpu_hour: 6.72
|
||||
gpu_count: 8
|
||||
gpu_model: "NVIDIA A100 40GB/80GB"
|
||||
notes: "Training and inference, 40GB or 80GB HBM2e"
|
||||
gpu_model: NVIDIA A100 40GB/80GB
|
||||
notes: Training and inference, 40GB or 80GB HBM2e
|
||||
VM.GPU.A10.1:
|
||||
per_gpu_hour: 0.72
|
||||
gpu_count: 1
|
||||
gpu_model: "NVIDIA A10"
|
||||
notes: "Inference workloads, cost-effective"
|
||||
gpu_model: NVIDIA A10
|
||||
notes: Inference workloads, cost-effective
|
||||
VM.GPU.A10.2:
|
||||
per_gpu_hour: 0.72
|
||||
gpu_count: 2
|
||||
gpu_model: "NVIDIA A10"
|
||||
notes: "Inference workloads"
|
||||
gpu_model: NVIDIA A10
|
||||
notes: Inference workloads
|
||||
BM.GPU.L40S:
|
||||
per_gpu_hour: 2.42
|
||||
gpu_count: 4
|
||||
gpu_model: "NVIDIA L40S"
|
||||
notes: "Ada Lovelace, inference and graphics"
|
||||
|
||||
# ── Secure Desktops ───────────────────────────────────────────────
|
||||
|
||||
gpu_model: NVIDIA L40S
|
||||
notes: Ada Lovelace, inference and graphics
|
||||
secure_desktops:
|
||||
per_desktop_month: 1750.00
|
||||
notes: "Managed virtual desktop infrastructure"
|
||||
|
||||
# ── Estimation Helpers ─────────────────────────────────────────────
|
||||
|
||||
per_desktop_month: 1750.0
|
||||
notes: Managed virtual desktop infrastructure
|
||||
estimation_helpers:
|
||||
typical_app_server:
|
||||
config: "VM.Standard.E5.Flex, 4 OCPU, 64 GB"
|
||||
monthly: 126.60 # (4 * 15.33) + (64 * 1.02)
|
||||
config: VM.Standard.E5.Flex, 4 OCPU, 64 GB
|
||||
monthly: 181.04
|
||||
typical_web_server:
|
||||
config: "VM.Standard.E5.Flex, 2 OCPU, 16 GB"
|
||||
monthly: 46.98 # (2 * 15.33) + (16 * 1.02)
|
||||
config: VM.Standard.E5.Flex, 2 OCPU, 16 GB
|
||||
monthly: 67.16
|
||||
typical_bastion:
|
||||
config: "VM.Standard.E5.Flex, 1 OCPU, 8 GB"
|
||||
monthly: 23.49 # (1 * 15.33) + (8 * 1.02)
|
||||
config: VM.Standard.E5.Flex, 1 OCPU, 8 GB
|
||||
monthly: 33.58
|
||||
typical_arm_app_server:
|
||||
config: "VM.Standard.A1.Flex, 4 OCPU, 24 GB"
|
||||
monthly: 50.96 # (4 * 9.27) + (24 * 0.58)
|
||||
|
||||
config: VM.Standard.A1.Flex, 4 OCPU, 24 GB
|
||||
monthly: 51.1
|
||||
discounts:
|
||||
preemptible: "~50% off on-demand"
|
||||
capacity_reservation: "~15% off on-demand (85% of list)"
|
||||
reserved_1yr: "~35% off on-demand"
|
||||
reserved_3yr: "~55% off on-demand"
|
||||
universal_credits: "Volume discounts on committed spend"
|
||||
|
||||
preemptible: ~50% off on-demand
|
||||
capacity_reservation: ~15% off on-demand (85% of list)
|
||||
reserved_1yr: ~35% off on-demand
|
||||
reserved_3yr: ~55% off on-demand
|
||||
universal_credits: Volume discounts on committed spend
|
||||
os_pricing:
|
||||
free:
|
||||
- "Oracle Linux"
|
||||
- "CentOS"
|
||||
- "Ubuntu"
|
||||
- "Oracle Autonomous Linux"
|
||||
- Oracle Linux
|
||||
- CentOS
|
||||
- Ubuntu
|
||||
- Oracle Autonomous Linux
|
||||
paid:
|
||||
windows_server:
|
||||
notes: "Pricing varies by edition, added to compute cost"
|
||||
notes: Pricing varies by edition, added to compute cost
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Containers, Kubernetes, and Serverless pricing.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── Oracle Kubernetes Engine (OKE) ────────────────────────────────
|
||||
|
||||
oke:
|
||||
basic_cluster:
|
||||
per_hour: "Free"
|
||||
notes: "Basic cluster management at no cost"
|
||||
enhanced_cluster:
|
||||
per_cluster_hour: 0.10
|
||||
monthly_per_cluster: 73.00
|
||||
notes: "Enhanced features: virtual nodes, workload identity, etc."
|
||||
virtual_nodes:
|
||||
notes: "Additional per-pod pricing on enhanced clusters"
|
||||
worker_nodes:
|
||||
notes: "Billed at standard compute shape rates"
|
||||
|
||||
# ── Container Instances ────────────────────────────────────────────
|
||||
|
||||
container_instances:
|
||||
notes: "Billed at compute rates: OCPU/hour + GB memory/hour"
|
||||
shapes_available:
|
||||
- "A1 (Arm)"
|
||||
- "E3 (AMD)"
|
||||
- "E4 (AMD)"
|
||||
|
||||
# ── Functions (Serverless) ─────────────────────────────────────────
|
||||
|
||||
functions:
|
||||
invocations:
|
||||
free_per_month: 2000000
|
||||
per_invocation_beyond: 0.0000002
|
||||
memory:
|
||||
free_gb_seconds_per_month: 400000
|
||||
per_gb_second_beyond: 0.00001417
|
||||
notes: "Generous free tier, very cost-effective for event-driven workloads"
|
||||
|
||||
# ── OCI Batch ──────────────────────────────────────────────────────
|
||||
|
||||
batch:
|
||||
notes: "Pay-as-you-go compute pricing, no additional service charge"
|
||||
@@ -1,283 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Database Service pricing for estimation purposes.
|
||||
currency: USD
|
||||
disclaimer: |
|
||||
Approximate pricing for estimation (within ~15%). Actual pricing varies by
|
||||
region, commitment level, and negotiated discounts. Always verify against
|
||||
https://www.oracle.com/cloud/pricing/
|
||||
---
|
||||
|
||||
# ── Autonomous AI Database (Serverless) ───────────────────────────
|
||||
# NOTE: ADB now uses ECPU billing model (not OCPU)
|
||||
|
||||
autonomous_database_serverless:
|
||||
billing_unit: ECPU
|
||||
license_included:
|
||||
ecpu_per_hour: 0.0420
|
||||
byol:
|
||||
ecpu_per_hour: 0.0168
|
||||
storage:
|
||||
per_gb_month: 0.0850
|
||||
per_tb_month: 87.04
|
||||
auto_scaling:
|
||||
notes: "Billed per ECPU-second for additional ECPUs above base. Same rate."
|
||||
adg_standby:
|
||||
notes: "Standby ECPU cost at same rate as primary. Storage shared (no extra)."
|
||||
backup:
|
||||
notes: "Automated backups included in storage cost. Manual backups use Object Storage rates."
|
||||
examples:
|
||||
8_ecpu_2tb_payg:
|
||||
monthly_li: "$2,699"
|
||||
monthly_byol: "$1,150"
|
||||
breakdown: "8 ECPU × $0.0420/hr × 730hr + 2048GB × $0.0850"
|
||||
8_ecpu_2tb_byol_with_adg:
|
||||
monthly: "$2,300"
|
||||
breakdown: "2 × (8 ECPU × $0.0168/hr × 730hr) + 2048GB × $0.0850"
|
||||
|
||||
# ── Autonomous AI JSON Database ────────────────────────────────────
|
||||
|
||||
autonomous_json_database:
|
||||
billing_unit: ECPU
|
||||
ecpu_per_hour: 0.0420
|
||||
storage_per_gb_month: 0.0850
|
||||
notes: "Same pricing as ADB-S, optimized for JSON document workloads"
|
||||
|
||||
# ── Autonomous Database Dedicated ──────────────────────────────────
|
||||
|
||||
autonomous_database_dedicated:
|
||||
billing_unit: ECPU
|
||||
infrastructure:
|
||||
# X9M / X8M — fixed rack shapes (legacy, still available in some regions)
|
||||
x9m:
|
||||
quarter_rack:
|
||||
base_per_hour: "~$10.50"
|
||||
monthly_estimate: "$7,500–$8,000"
|
||||
included: "2 DB servers, 3 storage servers, 100TB usable"
|
||||
half_rack:
|
||||
base_per_hour: "~$21.00"
|
||||
monthly_estimate: "$15,000–$16,000"
|
||||
included: "4 DB servers, 6 storage servers, 200TB usable"
|
||||
full_rack:
|
||||
base_per_hour: "~$42.00"
|
||||
monthly_estimate: "$30,000–$32,000"
|
||||
included: "8 DB servers, 12 storage servers, 400TB usable"
|
||||
# X11M — elastic scaling (new default as of 2025, replaces fixed rack shapes)
|
||||
x11m:
|
||||
model: "Elastic — 2 to 32 DB servers + 3 to 64 storage servers (no fixed rack shapes)"
|
||||
minimum_config: "2 DB servers minimum (cannot order 1 DB server) + 3 storage servers"
|
||||
billing: "Per ECPU per second (8-ECPU minimum per active DB VM)"
|
||||
infrastructure_rate: "NOT PUBLICLY LISTED — requires OCI PDM/sales confirmation"
|
||||
monthly_estimate: "Confirm with Oracle sales; X9M rates used as proxy for estimation"
|
||||
notes: |
|
||||
X11M is the current-generation Exadata infrastructure (announced 2025).
|
||||
Key changes vs X9M:
|
||||
- No fixed quarter/half/full rack — elastic scale in/out
|
||||
- MINIMUM: 2 DB servers + 3 storage servers (cannot provision less)
|
||||
- Infrastructure pricing parity with X9M (no premium) per Oracle comms,
|
||||
but exact per-hour rates are not published in the public price list
|
||||
- ECPU billing by the second (vs hourly in older generations)
|
||||
- Improved compute, storage density, and RDMA throughput vs X9M
|
||||
ecpu_pricing:
|
||||
license_included_per_hour: 0.0672
|
||||
byol_per_hour: 0.0504
|
||||
notes: |
|
||||
Infrastructure cost is fixed per rack size (X9M) or elastic per server (X11M). ECPU cost is on top.
|
||||
DEP (Database Enterprise Patching) co-location is at next maintenance window.
|
||||
Billing starts only at AVAILABLE state.
|
||||
Provisioning takes days to weeks depending on capacity.
|
||||
IMPORTANT: For X11M sizing, confirm infrastructure rates with PDM — use X9M as proxy only.
|
||||
|
||||
# ── Base Database Service (DBCS) ──────────────────────────────────
|
||||
|
||||
dbcs:
|
||||
billing_unit: ECPU
|
||||
license_included:
|
||||
ecpu_per_hour_se: 0.0336 # Standard Edition
|
||||
ecpu_per_hour_ee: 0.0420 # Enterprise Edition
|
||||
ecpu_per_hour_ee_hp: 0.0504 # High Performance
|
||||
ecpu_per_hour_ee_ep: 0.0672 # Extreme Performance — BYOL only on newer docs
|
||||
byol:
|
||||
ecpu_per_hour: 0.0168
|
||||
storage_per_gb_month: 0.0255
|
||||
notes: |
|
||||
SE = Standard Edition, EE = Enterprise Edition,
|
||||
HP = High Performance (partitioning, advanced compression, etc.),
|
||||
EP = Extreme Performance (RAC, Active Data Guard, In-Memory).
|
||||
Backup storage charged separately at Object Storage rates.
|
||||
examples:
|
||||
4_ecpu_ee_hp_500gb:
|
||||
monthly_li: "$160"
|
||||
breakdown: "4 ECPU × $0.0504/hr × 730hr + 500GB × $0.0255"
|
||||
|
||||
# ── Exadata Database Service Dedicated ─────────────────────────────
|
||||
|
||||
exadata_dedicated:
|
||||
billing_unit: ECPU
|
||||
infrastructure:
|
||||
# X9M — fixed rack shapes (available in all regions)
|
||||
x9m:
|
||||
quarter_rack:
|
||||
per_hour: 2.10
|
||||
monthly_estimate: "$1,533"
|
||||
half_rack:
|
||||
per_hour: 6.30
|
||||
monthly_estimate: "$4,599"
|
||||
full_rack:
|
||||
per_hour: 12.60
|
||||
monthly_estimate: "$9,198"
|
||||
# X11M — elastic scaling (current generation, replaces fixed rack shapes)
|
||||
x11m:
|
||||
model: "Elastic — 2 to 32 DB servers + 3 to 64 storage servers"
|
||||
minimum_config: "2 DB servers + 3 storage servers (hard minimum — applies to ADB-D and ExaCS)"
|
||||
billing: "Per ECPU per second (8-ECPU minimum per active DB VM)"
|
||||
infrastructure_rate: "Line items exist in OCI price list ('Database Server - X11M' and 'Storage Server - X11M') but dollar amounts not visible without Oracle Cost Estimator or authenticated access"
|
||||
proxy_for_estimation: "Use X9M quarter rack ($2.10/hr) as proxy for 2 DB + 3 storage"
|
||||
notes: |
|
||||
X11M is confirmed current-gen Exadata for both ExaCS and ADB-D on OCI.
|
||||
MINIMUM: 2 DB servers + 3 storage servers — cannot provision less (verified against Oracle datasheets).
|
||||
Per-server line items exist in price list but amounts require Oracle Cost Estimator or PDM quote.
|
||||
Use X9M quarter rack ($2.10/hr infrastructure) as proxy for minimum config estimation.
|
||||
ecpu_pricing:
|
||||
license_included_per_hour: 0.0504
|
||||
byol_per_hour: 0.0420
|
||||
what_is_included:
|
||||
- "Exadata smart storage (flash cache, storage indexes)"
|
||||
- "Automated patching (GI + DB separate schedules)"
|
||||
- "Automated backups to Object Storage"
|
||||
- "RAC licensing included in Extreme Performance edition"
|
||||
what_is_extra:
|
||||
- "Data Guard setup and standby infrastructure"
|
||||
- "Additional storage beyond rack capacity"
|
||||
- "Object Storage for long-term backup retention"
|
||||
gotchas:
|
||||
- "Infrastructure cost is fixed regardless of ECPU utilization (X9M)."
|
||||
- "X11M elastic model: scale in/out by server, not by rack."
|
||||
- "Provisioning takes 4-8 hours."
|
||||
- "X11M has improved storage density, RDMA throughput, and CPU vs X9M."
|
||||
|
||||
# ── Exadata Exascale ───────────────────────────────────────────────
|
||||
|
||||
exadata_exascale:
|
||||
billing_unit: ECPU
|
||||
ecpu_per_hour: 0.0504
|
||||
storage:
|
||||
notes: "Storage priced separately per Exascale vault capacity"
|
||||
notes: "Elastic scaling of compute and storage independently. Next-gen Exadata."
|
||||
|
||||
# ── Exadata Cloud@Customer ─────────────────────────────────────────
|
||||
|
||||
exadata_cloud_at_customer:
|
||||
billing_unit: ECPU
|
||||
ecpu_pricing:
|
||||
license_included_per_hour: 0.0504
|
||||
byol_per_hour: 0.0420
|
||||
infrastructure:
|
||||
base_per_hour: 7.35
|
||||
monthly_estimate: "$5,365"
|
||||
notes: "Exadata infrastructure in customer datacenter, managed by Oracle"
|
||||
|
||||
# ── MySQL HeatWave ─────────────────────────────────────────────────
|
||||
|
||||
mysql_heatwave:
|
||||
billing_unit: ECPU
|
||||
ecpu_per_hour: 0.0180
|
||||
storage_per_gb_month: 0.0085
|
||||
heatwave_cluster:
|
||||
notes: "Additional capacity pricing for HeatWave in-memory acceleration"
|
||||
free_tier:
|
||||
notes: "MySQL HeatWave Free Tier available with limits"
|
||||
mysql_heatwave_on_aws:
|
||||
ecpu_per_hour: 0.0180
|
||||
notes: "Cross-cloud deployment, same base pricing"
|
||||
|
||||
# ── PostgreSQL ─────────────────────────────────────────────────────
|
||||
|
||||
postgresql:
|
||||
ocpu_per_hour: 0.0168
|
||||
storage_per_gb_month: 0.0850
|
||||
notes: "Managed PostgreSQL, includes HA options"
|
||||
|
||||
# ── Cache with Redis ───────────────────────────────────────────────
|
||||
|
||||
cache_redis:
|
||||
up_to_10gb:
|
||||
per_gb_hour: 0.0194
|
||||
monthly_per_gb: 14.16
|
||||
above_10gb:
|
||||
per_gb_hour: 0.0136
|
||||
monthly_per_gb: 9.93
|
||||
|
||||
# ── OpenSearch ─────────────────────────────────────────────────────
|
||||
|
||||
opensearch:
|
||||
per_node_hour: 0.0252
|
||||
notes: "HA configuration, pricing per node"
|
||||
|
||||
# ── NoSQL Database ─────────────────────────────────────────────────
|
||||
|
||||
nosql:
|
||||
provisioned:
|
||||
storage_per_gb_month: 0.0085
|
||||
write_unit_per_month: 0.0001
|
||||
read_unit_per_month: 0.000020
|
||||
on_demand:
|
||||
storage_per_gb_month: 0.0085
|
||||
notes: "Auto-scaled read/write units"
|
||||
free_tier:
|
||||
storage_gb: 25
|
||||
write_units: 50
|
||||
read_units: 50
|
||||
max_tables: 3
|
||||
|
||||
# ── TimesTen for OKE ──────────────────────────────────────────────
|
||||
|
||||
timesten:
|
||||
x86_ocpu_per_hour: 0.0252
|
||||
arm_ocpu_per_hour: 0.0168
|
||||
notes: "In-memory relational database deployed on Kubernetes"
|
||||
|
||||
# ── Data Safe ──────────────────────────────────────────────────────
|
||||
|
||||
data_safe:
|
||||
per_target_month: 0.0150
|
||||
audit_records_per_10k_month: 0.0001
|
||||
|
||||
# ── Database Migration ─────────────────────────────────────────────
|
||||
|
||||
database_migration:
|
||||
per_migration_hour: 0.0420
|
||||
notes: "First 183 days free if migration is active"
|
||||
|
||||
# ── Database Autonomous Recovery ───────────────────────────────────
|
||||
|
||||
database_autonomous_recovery:
|
||||
per_gb_virtualized_month: 0.0085
|
||||
notes: "Autonomous backup recovery service"
|
||||
|
||||
# ── GoldenGate ─────────────────────────────────────────────────────
|
||||
|
||||
goldengate:
|
||||
ocpu_per_hour: 0.0252
|
||||
byol_available: true
|
||||
notes: "Real-time data integration and replication"
|
||||
|
||||
# ── Estimation Helpers ─────────────────────────────────────────────
|
||||
|
||||
estimation_helpers:
|
||||
monthly_hours: 730
|
||||
byol_savings: "50-60% on ECPU cost for Oracle Database products"
|
||||
adb_s_sweet_spot: "4-32 ECPUs with auto-scaling. Below 4, consider Always Free. Above 128, consider ADB-D or ExaCS."
|
||||
cost_comparison_tip: |
|
||||
When comparing with AWS RDS or Azure SQL MI, include:
|
||||
- OCI inbound data transfer is free
|
||||
- OCI outbound is ~80% cheaper than AWS
|
||||
- OCI BYOL discount is deeper than AWS BYOL
|
||||
- ADB-S includes patching, tuning, indexing — RDS does not
|
||||
- ADB now uses ECPU (not OCPU) — 1 ECPU ≈ fraction of an OCPU
|
||||
|
||||
reserved_discounts:
|
||||
one_year: "~35-40% vs PAYG"
|
||||
three_year: "~55-65% vs PAYG"
|
||||
notes: "Available for all database services. Commitment is per-region."
|
||||
@@ -1,59 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Developer Services pricing.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── APEX Application Development ──────────────────────────────────
|
||||
|
||||
apex:
|
||||
ecpu_per_hour: 0.36
|
||||
free_tier: true
|
||||
notes: "Low-code development platform, free tier available"
|
||||
|
||||
# ── Visual Builder ─────────────────────────────────────────────────
|
||||
|
||||
visual_builder:
|
||||
ocpu_per_hour: 0.0252
|
||||
notes: "Low-code app builder with storage"
|
||||
|
||||
# ── DevOps ─────────────────────────────────────────────────────────
|
||||
|
||||
devops:
|
||||
pipeline_execution: "Free"
|
||||
notes: "No charge for pipeline execution; compute/memory billed separately"
|
||||
|
||||
# ── Blockchain Platform ───────────────────────────────────────────
|
||||
|
||||
blockchain:
|
||||
ocpu_per_hour: 0.0252 - 0.0504
|
||||
notes: "Plus storage costs"
|
||||
|
||||
# ── IoT Platform ──────────────────────────────────────────────────
|
||||
|
||||
iot:
|
||||
ecpu_per_hour: 0.0360
|
||||
notes: "Plus storage costs"
|
||||
|
||||
# ── Media Flow ─────────────────────────────────────────────────────
|
||||
|
||||
media_flow:
|
||||
per_minute: 0.005 - 0.120
|
||||
notes: "Varies by codec, resolution, and fps"
|
||||
|
||||
# ── Media Streams ──────────────────────────────────────────────────
|
||||
|
||||
media_streams:
|
||||
per_gb_packaged: 0.015
|
||||
|
||||
# ── Tuxedo ─────────────────────────────────────────────────────────
|
||||
|
||||
tuxedo:
|
||||
ocpu_per_hour: 0.0252 - 0.0504
|
||||
notes: "For legacy Tuxedo workload migration"
|
||||
|
||||
# ── WebCenter ──────────────────────────────────────────────────────
|
||||
|
||||
webcenter:
|
||||
ocpu_per_hour: 0.0252 - 0.0504
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Hybrid Cloud and VMware Solution pricing.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── Oracle Cloud VMware Solution (OCVS) ───────────────────────────
|
||||
|
||||
vmware_solution:
|
||||
base_nodes:
|
||||
BM.Standard2.12:
|
||||
per_node_hour: 2.10 - 4.20
|
||||
notes: "Hourly to 3-year commitment range"
|
||||
BM.Standard3.16:
|
||||
per_node_hour: 3.03 - 6.06
|
||||
BM.Standard.E4.32:
|
||||
per_node_hour: 4.20 - 8.40
|
||||
BM.Standard.E5.48:
|
||||
per_node_hour: 4.99 - 9.98
|
||||
expansion:
|
||||
ocpu_per_hour: 0.0168 - 0.0420
|
||||
notes: "Commitment-based pricing"
|
||||
hcx_enterprise:
|
||||
ocpu_per_hour: 0.0084
|
||||
minimum_commitment: "1 month"
|
||||
gpu_storage_nodes:
|
||||
per_node_hour: 2.10 - 4.20
|
||||
notes: "Commitment-based pricing"
|
||||
|
||||
# ── Compute Cloud@Customer ─────────────────────────────────────────
|
||||
|
||||
compute_cloud_at_customer:
|
||||
e6_compute:
|
||||
ocpu_per_hour: 0.0336 - 0.0504
|
||||
storage:
|
||||
per_gb_month: 0.0085 - 0.0170
|
||||
load_balancer:
|
||||
per_hour: 0.10
|
||||
|
||||
# ── Managed Service for Mac ────────────────────────────────────────
|
||||
|
||||
managed_mac:
|
||||
per_server_hour:
|
||||
m2_pro: 1.20
|
||||
m4_pro: 4.20
|
||||
notes: "Range depends on Mac model (M2 Pro to M4 Pro)"
|
||||
|
||||
# ── Roving Edge Infrastructure ─────────────────────────────────────
|
||||
|
||||
roving_edge:
|
||||
per_device_day: 300 - 1000
|
||||
notes: "Portable compute/GPU/storage for edge and disconnected scenarios"
|
||||
@@ -1,55 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Integration and Middleware pricing.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── Integration Cloud ─────────────────────────────────────────────
|
||||
|
||||
integration_cloud:
|
||||
per_5k_messages_hour: 0.36 - 0.72
|
||||
notes: "Standard and Enterprise editions"
|
||||
|
||||
# ── API Management ─────────────────────────────────────────────────
|
||||
|
||||
api_management:
|
||||
per_api_call: 0.0000005
|
||||
monthly_1m_calls: 0.50
|
||||
notes: "Very low cost per call"
|
||||
|
||||
# ── Data Integration ───────────────────────────────────────────────
|
||||
|
||||
data_integration:
|
||||
workspace_per_hour: 0.0252
|
||||
data_processed_per_gb_hour: 0.0252
|
||||
|
||||
# ── Data Integrator ────────────────────────────────────────────────
|
||||
|
||||
data_integrator:
|
||||
ocpu_per_hour: 0.0252
|
||||
|
||||
# ── Streaming (Kafka compatible) ──────────────────────────────────
|
||||
|
||||
streaming:
|
||||
storage_per_gb_hour: 0.025
|
||||
data_transfer_per_gb: 0.025
|
||||
|
||||
streaming_with_kafka:
|
||||
ocpu_per_hour: 0.0252
|
||||
|
||||
# ── Queue ──────────────────────────────────────────────────────────
|
||||
|
||||
queue:
|
||||
free_per_month: 1000000 # requests
|
||||
per_request_beyond: 0.0000005
|
||||
notes: "1M free requests/month, very cost-effective for decoupling"
|
||||
|
||||
# ── SOA Suite ──────────────────────────────────────────────────────
|
||||
|
||||
soa_suite:
|
||||
ocpu_per_hour: 0.0504 - 0.0672
|
||||
notes: "For legacy SOA workload migration"
|
||||
|
||||
# ── GoldenGate ─────────────────────────────────────────────────────
|
||||
# See database.yaml for GoldenGate pricing
|
||||
@@ -1,70 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Networking pricing for estimation purposes.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── Load Balancing ─────────────────────────────────────────────────
|
||||
|
||||
load_balancer:
|
||||
base_instance_per_hour: 0.10
|
||||
bandwidth_per_mbps_hour: 0.0084
|
||||
monthly_base: 73.00
|
||||
notes: "Flexible shape, bandwidth billed separately"
|
||||
|
||||
network_load_balancer:
|
||||
per_hour: "Free"
|
||||
notes: "Layer 4, no per-hour charge, data processing fees apply"
|
||||
|
||||
# ── FastConnect ────────────────────────────────────────────────────
|
||||
|
||||
fastconnect:
|
||||
port_per_hour:
|
||||
1gbps: 0.30
|
||||
2gbps: 0.50
|
||||
5gbps: 1.26
|
||||
10gbps: 2.52
|
||||
40gbps: 5.04
|
||||
100gbps: 6.30
|
||||
400gbps: 12.60
|
||||
monthly_730h:
|
||||
1gbps: 219.00
|
||||
10gbps: 1839.60
|
||||
100gbps: 4599.00
|
||||
data_transfer: "Free (ingress and egress)"
|
||||
notes: "Private dedicated connectivity. No data transfer charges."
|
||||
|
||||
# ── VPN Connect ────────────────────────────────────────────────────
|
||||
|
||||
vpn_connect:
|
||||
notes: "No additional charge for IPSec VPN tunnels. Included with DRG."
|
||||
|
||||
# ── DNS ────────────────────────────────────────────────────────────
|
||||
|
||||
dns:
|
||||
queries_included_per_month: 1000000
|
||||
additional: "Free for most use cases"
|
||||
notes: "1M queries/month included at no cost"
|
||||
|
||||
# ── WAF ────────────────────────────────────────────────────────────
|
||||
|
||||
waf:
|
||||
notes: "Pricing based on requests processed. See OCI price list for current rates."
|
||||
|
||||
# ── Data Transfer Summary ──────────────────────────────────────────
|
||||
|
||||
data_transfer:
|
||||
ingress: "Free (all sources)"
|
||||
egress_internet:
|
||||
first_10tb_month: "Free"
|
||||
per_gb_beyond: 0.0085
|
||||
inter_region:
|
||||
per_gb: 0.0085
|
||||
fastconnect: "Free (both directions)"
|
||||
key_advantage: |
|
||||
OCI is dramatically cheaper than hyperscalers for data transfer:
|
||||
- AWS charges $0.09/GB egress (OCI: $0.0085 after 10TB free)
|
||||
- Azure charges $0.087/GB egress
|
||||
- GCP charges $0.12/GB egress
|
||||
- OCI FastConnect egress is FREE (AWS DirectConnect charges per GB)
|
||||
@@ -1,89 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Observability and Management pricing.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── Monitoring ─────────────────────────────────────────────────────
|
||||
|
||||
monitoring:
|
||||
ingestion:
|
||||
free_per_month: 500000000 # 500M datapoints
|
||||
per_datapoint_beyond: 0.00002
|
||||
retrieval:
|
||||
free_per_month: 1000000000 # 1B datapoints
|
||||
per_datapoint_beyond: 0.00002
|
||||
notes: "Very generous free tier for most workloads"
|
||||
|
||||
# ── Logging ────────────────────────────────────────────────────────
|
||||
|
||||
logging:
|
||||
free_per_month_gb: 10
|
||||
per_gb_month_beyond: 0.0050
|
||||
notes: "10 GB/month free, very affordable"
|
||||
|
||||
# ── Log Analytics ──────────────────────────────────────────────────
|
||||
|
||||
log_analytics:
|
||||
per_storage_unit_month: 2.50 - 5.00
|
||||
storage_unit_size_gb: 300
|
||||
notes: "1 storage unit = 300 GB"
|
||||
|
||||
# ── Notifications ──────────────────────────────────────────────────
|
||||
|
||||
notifications:
|
||||
free_per_month:
|
||||
deliveries: 1000000
|
||||
emails: 1000
|
||||
per_operation_beyond: 0.00001
|
||||
per_email_beyond: 0.00001
|
||||
|
||||
# ── Events ─────────────────────────────────────────────────────────
|
||||
|
||||
events:
|
||||
notes: "No additional charge for Events service"
|
||||
|
||||
# ── APM / Application Performance Monitoring ──────────────────────
|
||||
|
||||
apm:
|
||||
notes: "Pricing based on data ingestion volume and synthetic monitors"
|
||||
|
||||
# ── Database Management ────────────────────────────────────────────
|
||||
|
||||
database_management:
|
||||
ecpu_per_hour: 0.0360
|
||||
notes: "Fleet-level database monitoring and management"
|
||||
|
||||
# ── Ops Insights ───────────────────────────────────────────────────
|
||||
|
||||
ops_insights:
|
||||
basic: "Free"
|
||||
autonomous: "Free"
|
||||
cloud_external:
|
||||
ocpu_per_hour: 0.0420
|
||||
notes: "Basic and Autonomous tiers are free"
|
||||
|
||||
# ── Email Delivery ─────────────────────────────────────────────────
|
||||
|
||||
email_delivery:
|
||||
per_1k_emails: 0.00001 - 0.000015
|
||||
|
||||
# ── Full Stack Disaster Recovery ───────────────────────────────────
|
||||
|
||||
full_stack_dr:
|
||||
ecpu_per_hour: 0.0360
|
||||
ocpu_per_hour: 0.0420
|
||||
notes: "Orchestrates DR failover across compute, database, and networking"
|
||||
|
||||
# ── Fleet Application Management ──────────────────────────────────
|
||||
|
||||
fleet_app_management:
|
||||
per_managed_resource_month: 3.00 - 7.50
|
||||
|
||||
# ── OS & Java Management ──────────────────────────────────────────
|
||||
|
||||
os_management_hub: "Free"
|
||||
java_management_service: "Free"
|
||||
autonomous_linux: "Free"
|
||||
resource_analytics: "Free"
|
||||
1387
kb/pricing/oci-sku-catalog.yaml
Normal file
1387
kb/pricing/oci-sku-catalog.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,83 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI pricing models and discount structures.
|
||||
---
|
||||
|
||||
models:
|
||||
payg:
|
||||
name: "Pay As You Go"
|
||||
commitment: none
|
||||
discount: none
|
||||
billing: "Per second (compute), per hour (database), per month (storage)"
|
||||
when_to_use:
|
||||
- "Variable/unpredictable workloads"
|
||||
- "Short-term projects"
|
||||
- "Dev/test environments"
|
||||
- "Initial cloud adoption (before committing)"
|
||||
|
||||
monthly_flex:
|
||||
name: "Monthly Flex (Universal Credits)"
|
||||
commitment: "Minimum $1,000/month or custom commitment"
|
||||
discount: "Volume discounts on committed spend"
|
||||
billing: "Committed credits consumed by usage"
|
||||
when_to_use:
|
||||
- "Steady-state production workloads"
|
||||
- "Known baseline consumption"
|
||||
- "Multiple services across OCI"
|
||||
discount_tiers:
|
||||
- spend: "$1K-$10K/month"
|
||||
discount: "~5-10%"
|
||||
- spend: "$10K-$50K/month"
|
||||
discount: "~10-20%"
|
||||
- spend: "$50K+/month"
|
||||
discount: "~20-30% (negotiated)"
|
||||
|
||||
annual_flex:
|
||||
name: "Annual Flex (Committed)"
|
||||
commitment: "1-year or 3-year commitment"
|
||||
discount: "Deeper discounts than monthly flex"
|
||||
when_to_use:
|
||||
- "Established production workloads with predictable spend"
|
||||
- "Organizations committed to OCI long-term"
|
||||
|
||||
byol:
|
||||
name: "Bring Your Own License"
|
||||
discount: "~50% on database OCPU costs"
|
||||
eligible:
|
||||
- "Oracle Database Enterprise Edition"
|
||||
- "Oracle Database Standard Edition 2"
|
||||
- "Oracle WebLogic"
|
||||
- "Oracle Java SE"
|
||||
conversion: "1 processor license = 2 OCPUs"
|
||||
when_to_use:
|
||||
- "Existing Oracle on-prem licenses with active support"
|
||||
- "Licenses not being used elsewhere"
|
||||
when_NOT_to_use:
|
||||
- "No existing licenses"
|
||||
- "Licenses still needed for on-prem during migration"
|
||||
- "Standard Edition workloads on ADB (requires EE)"
|
||||
|
||||
reserved_capacity:
|
||||
name: "Reserved Capacity"
|
||||
commitment: "1-year or 3-year for specific shapes"
|
||||
discount:
|
||||
1_year: "~35% off on-demand"
|
||||
3_year: "~55% off on-demand"
|
||||
when_to_use:
|
||||
- "Known compute shapes running 24/7"
|
||||
- "Predictable database capacity"
|
||||
notes: "Shape-specific, less flexible than Universal Credits"
|
||||
|
||||
estimation_approach:
|
||||
step_1: "Calculate PAYG cost first (baseline)"
|
||||
step_2: "Apply BYOL if customer has eligible licenses"
|
||||
step_3: "Show savings with Monthly Flex / Annual Flex for steady-state"
|
||||
step_4: "Compare total annual cost vs current on-prem spending"
|
||||
step_5: "Include migration costs in year 1"
|
||||
assumptions_to_state:
|
||||
- "Hours per month (730 for 24/7)"
|
||||
- "Auto-scaling hours per day (estimate)"
|
||||
- "Data transfer volumes"
|
||||
- "Backup retention"
|
||||
- "Support tier"
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Security service pricing.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
# ── Access Governance ──────────────────────────────────────────────
|
||||
|
||||
access_governance:
|
||||
premium:
|
||||
workforce_user_month: 0.0018 - 0.0036
|
||||
consumer_user_month: 0.36
|
||||
for_oracle_workloads:
|
||||
workforce_user_month: 0.0009 - 0.0018
|
||||
consumer_user_month: 0.36
|
||||
for_oci:
|
||||
workforce_user_month: 0.00009 - 0.00018
|
||||
|
||||
# ── Vault ──────────────────────────────────────────────────────────
|
||||
|
||||
vault:
|
||||
notes: "Key management — see OCI price list for current rates. Free tier for software keys."
|
||||
|
||||
# ── Cloud Guard ────────────────────────────────────────────────────
|
||||
|
||||
cloud_guard:
|
||||
notes: "Free for OCI tenancy monitoring and threat detection"
|
||||
|
||||
# ── Security Zones ─────────────────────────────────────────────────
|
||||
|
||||
security_zones:
|
||||
notes: "Free — policy enforcement on compartments"
|
||||
|
||||
# ── Vulnerability Scanning ─────────────────────────────────────────
|
||||
|
||||
vulnerability_scanning:
|
||||
notes: "Free — host and container image scanning"
|
||||
|
||||
# ── Certificates ───────────────────────────────────────────────────
|
||||
|
||||
certificates:
|
||||
notes: "Free — TLS certificate management"
|
||||
|
||||
# ── Bastion ────────────────────────────────────────────────────────
|
||||
|
||||
bastion:
|
||||
notes: "Free — managed SSH/RDP bastion service"
|
||||
|
||||
# ── Network Firewall ──────────────────────────────────────────────
|
||||
|
||||
network_firewall:
|
||||
notes: "Pricing based on instance hours and data processed"
|
||||
|
||||
# ── Data Safe ──────────────────────────────────────────────────────
|
||||
# See database.yaml for Data Safe pricing
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
last_verified: 2025-09-11
|
||||
source: https://www.oracle.com/cloud/price-list/
|
||||
description: OCI Storage pricing for estimation purposes.
|
||||
currency: USD
|
||||
---
|
||||
|
||||
block_volume:
|
||||
balanced:
|
||||
per_gb_month: 0.0255
|
||||
per_tb_month: 26.11
|
||||
higher_performance:
|
||||
per_gb_month: 0.0340
|
||||
per_tb_month: 34.82
|
||||
lower_cost:
|
||||
per_gb_month: 0.0170
|
||||
per_tb_month: 17.41
|
||||
uhp:
|
||||
notes: "Priced per VPU, varies by configuration"
|
||||
boot_volume:
|
||||
free_tier: "200 GB included"
|
||||
additional: "Same as block volume pricing"
|
||||
backup:
|
||||
per_gb_month: 0.0050
|
||||
|
||||
object_storage:
|
||||
standard:
|
||||
per_gb_month: 0.0255
|
||||
per_tb_month: 26.11
|
||||
infrequent_access:
|
||||
per_gb_month: 0.0100
|
||||
per_tb_month: 10.24
|
||||
archive:
|
||||
per_gb_month: 0.0026
|
||||
per_tb_month: 2.66
|
||||
api_requests:
|
||||
per_10k_put: 0.0040
|
||||
per_10k_get: 0.0003
|
||||
free_tier:
|
||||
storage_gb: 10
|
||||
requests: 50000
|
||||
|
||||
file_storage:
|
||||
per_gb_month: 0.0340
|
||||
per_tb_month: 34.82
|
||||
|
||||
data_transfer:
|
||||
ingress: "Free"
|
||||
egress_internet:
|
||||
first_10tb_month: "Free"
|
||||
per_gb_after: 0.0085
|
||||
inter_region:
|
||||
per_gb: 0.0085
|
||||
fastconnect:
|
||||
ingress: "Free"
|
||||
egress: "Free"
|
||||
notes: |
|
||||
OCI egress pricing is significantly cheaper than AWS/Azure/GCP.
|
||||
First 10 TB/month internet egress is free.
|
||||
FastConnect egress is free (no per-GB charge).
|
||||
@@ -20,15 +20,18 @@ features:
|
||||
ha_dr_options:
|
||||
local_ha: "Built-in TAC (Transparent Application Continuity) — ~0 perceived RTO"
|
||||
same_region_adg: "Autonomous Data Guard standby — synchronous, RPO 0"
|
||||
cross_region_adg: "Cross-region ADG — asynchronous only, RPO seconds, RTO < 15 min"
|
||||
cross_region_adg: "Cross-region ADG — asynchronous only, RPO seconds (switchover RPO 0, manual failover RPO up to 1 min), RTO < 10 min"
|
||||
cross_region_auto_failover: "NOT available — cross-region requires manual switchover/failover only"
|
||||
|
||||
limits:
|
||||
max_ocpu: 128
|
||||
max_storage_tb: 383
|
||||
max_auto_scale: "3x base OCPUs"
|
||||
max_ecpu: 512
|
||||
max_ocpu_legacy: 128
|
||||
max_storage_tb: 384
|
||||
max_auto_scale: "3x base ECPUs"
|
||||
auto_scale_activation: "2-3 minutes"
|
||||
min_ocpu: 1
|
||||
min_ecpu: 2
|
||||
min_storage_tb: 1
|
||||
notes: "ECPU is now the default billing unit. 4 ECPUs ≈ 1 OCPU. OCPU billing is legacy."
|
||||
|
||||
variants:
|
||||
- id: adb_s
|
||||
@@ -66,12 +69,14 @@ when_not_to_use:
|
||||
|
||||
sizing:
|
||||
adb_s:
|
||||
min_ocpu: 1
|
||||
max_ocpu: 128
|
||||
auto_scaling: "Up to 3x base OCPUs (takes 2-3 minutes to activate)"
|
||||
sizing_guidance: "Size base OCPUs for P75 sustained load, not P50. Auto-scaling covers peaks but has activation latency."
|
||||
min_ecpu: 2
|
||||
max_ecpu: 512
|
||||
min_ocpu_legacy: 1
|
||||
max_ocpu_legacy: 128
|
||||
auto_scaling: "Up to 3x base ECPUs (takes 2-3 minutes to activate)"
|
||||
sizing_guidance: "Size base ECPUs for P75 sustained load, not P50. Auto-scaling covers peaks but has activation latency. 4 ECPUs ≈ 1 OCPU."
|
||||
storage_min_tb: 1
|
||||
storage_max_tb: 383
|
||||
storage_max_tb: 384
|
||||
iops: "Proportional to OCPU count, Exadata storage servers"
|
||||
|
||||
adb_d:
|
||||
@@ -105,9 +110,9 @@ gotchas:
|
||||
severity: MEDIUM
|
||||
description: "Cross-region Autonomous Data Guard is async only (RPO > 0). For zero RPO, need same-region standby or ADB-D with local Data Guard."
|
||||
|
||||
- id: adb_19c_only
|
||||
- id: adb_version
|
||||
severity: LOW
|
||||
description: "ADB currently runs Oracle 19c. If customer needs 23ai features, verify availability."
|
||||
description: "ADB now defaults to Oracle 26ai in all commercial regions. 19c is legacy. Verify customer version requirements."
|
||||
|
||||
implied_dependencies:
|
||||
- service: service_gateway
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
---
|
||||
last_verified: 2026-03-14
|
||||
last_verified: 2026-04-24
|
||||
service: OCI Compute
|
||||
category: compute
|
||||
oci_color: "#4F7B6E"
|
||||
changelog:
|
||||
- date: "2026-04-24"
|
||||
change: "Added missing shapes surfaced by discover+WebFetch: VM/BM.Standard.E6.Ax, VM/BM.Standard.A4.Ax, and full X12 family (VM.Standard4.Ax.Flex 39 OCPU / 360 GB, BM.Standard4.Ax.120 latest-gen bare metal). Verified against docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm."
|
||||
---
|
||||
|
||||
what: Virtual machines and bare metal instances. Flexible shapes allow custom
|
||||
@@ -11,9 +14,16 @@ what: Virtual machines and bare metal instances. Flexible shapes allow custom
|
||||
shape_families:
|
||||
- name: VM.Standard.E5.Flex
|
||||
processor: "AMD EPYC 9J14 (Genoa)"
|
||||
max_ocpu: 94
|
||||
max_ocpu: 126
|
||||
memory_per_ocpu_gb: "1-64 GB per OCPU"
|
||||
use_for: "General purpose, most workloads"
|
||||
- name: VM.Standard.E6.Flex
|
||||
processor: "AMD EPYC 9J45 (Turin)"
|
||||
max_ocpu: 126
|
||||
max_memory_gb: 1454
|
||||
memory_per_ocpu_gb: "1-64 GB per OCPU"
|
||||
network_gbps: 99
|
||||
use_for: "Latest generation general purpose"
|
||||
- name: VM.Standard3.Flex
|
||||
processor: "Intel Xeon (Ice Lake)"
|
||||
max_ocpu: 32
|
||||
@@ -21,14 +31,70 @@ shape_families:
|
||||
use_for: "Intel-optimized workloads"
|
||||
- name: VM.Standard.A2.Flex
|
||||
processor: "Ampere Altra (Arm)"
|
||||
max_ocpu: 80
|
||||
max_ocpu: 78
|
||||
memory_per_ocpu_gb: "1-64 GB per OCPU"
|
||||
use_for: "Arm-compatible workloads, cost optimization"
|
||||
- name: VM.Standard.A4.Flex
|
||||
processor: "Arm"
|
||||
max_ocpu: 45
|
||||
max_memory_gb: 700
|
||||
network_gbps: 100
|
||||
use_for: "Latest Arm generation, cloud-native workloads"
|
||||
- name: VM.Optimized3.Flex
|
||||
processor: "Intel Xeon (Ice Lake)"
|
||||
max_ocpu: 18
|
||||
memory_per_ocpu_gb: "1-64 GB per OCPU"
|
||||
use_for: "High-frequency trading, HPC"
|
||||
- name: VM.Standard.E6.Ax.Flex
|
||||
processor: "AMD EPYC (Ampere-branded E6 variant)"
|
||||
max_ocpu: 94
|
||||
max_memory_gb: 712
|
||||
network_gbps: 99
|
||||
use_for: "E6 Ampere-variant general purpose"
|
||||
- name: VM.Standard.A4.Ax.Flex
|
||||
processor: "Arm (A4 Ampere-branded variant)"
|
||||
max_ocpu: 45
|
||||
max_memory_gb: 720
|
||||
network_gbps: 100
|
||||
use_for: "A4 Ampere-variant Arm workloads"
|
||||
- name: VM.Standard4.Ax.Flex
|
||||
processor: "AMD EPYC (X12 Ampere-branded)"
|
||||
max_ocpu: 39
|
||||
max_memory_gb: 360
|
||||
network_gbps: 99
|
||||
use_for: "X12-generation general purpose (latest)"
|
||||
- name: BM.Standard.E5
|
||||
processor: "AMD EPYC 9J14 (Genoa)"
|
||||
ocpus: 192
|
||||
use_for: "Bare metal general purpose"
|
||||
- name: BM.Standard.E6
|
||||
processor: "AMD EPYC 9J45 (Turin)"
|
||||
ocpus: 256
|
||||
use_for: "Bare metal latest generation"
|
||||
- name: BM.Standard.E6.Ax.192
|
||||
processor: "AMD EPYC (E6 Ampere-branded variant)"
|
||||
ocpus: 192
|
||||
max_memory_gb: 1536
|
||||
network_gbps: 200
|
||||
use_for: "Bare metal E6 Ampere-variant"
|
||||
- name: BM.Standard.A4.48
|
||||
processor: "Arm (A4)"
|
||||
ocpus: 48
|
||||
max_memory_gb: 768
|
||||
network_gbps: 100
|
||||
use_for: "Bare metal A4 Arm general purpose"
|
||||
- name: BM.Standard.A4.Ax.48
|
||||
processor: "Arm (A4 Ampere-branded variant)"
|
||||
ocpus: 48
|
||||
max_memory_gb: 768
|
||||
network_gbps: 100
|
||||
use_for: "Bare metal A4 Ampere-variant Arm"
|
||||
- name: BM.Standard4.Ax.120
|
||||
processor: "AMD EPYC (X12 Ampere-branded)"
|
||||
ocpus: 120
|
||||
max_memory_gb: 1152
|
||||
network_gbps: 200
|
||||
use_for: "Bare metal X12 latest generation"
|
||||
- name: VM.GPU.A10.1
|
||||
processor: "NVIDIA A10"
|
||||
gpu_count: 1
|
||||
@@ -37,6 +103,38 @@ shape_families:
|
||||
processor: "NVIDIA H100 (8 GPUs)"
|
||||
gpu_count: 8
|
||||
use_for: "AI/ML training, large model inference"
|
||||
- name: BM.GPU.H200.8
|
||||
processor: "NVIDIA H200 (8 GPUs)"
|
||||
gpu_count: 8
|
||||
use_for: "AI/ML training, large model inference (higher memory bandwidth)"
|
||||
- name: BM.GPU.B200.8
|
||||
processor: "NVIDIA B200 (8 GPUs)"
|
||||
gpu_count: 8
|
||||
use_for: "Next-gen AI training and inference"
|
||||
- name: BM.GPU.B300.8
|
||||
processor: "NVIDIA B300 (8 GPUs)"
|
||||
gpu_count: 8
|
||||
use_for: "Next-gen AI training and inference"
|
||||
- name: BM.GPU.GB200.4
|
||||
processor: "NVIDIA GB200 (4 GPUs)"
|
||||
gpu_count: 4
|
||||
use_for: "Grace Blackwell superchip, AI training"
|
||||
- name: BM.GPU.GB300.4
|
||||
processor: "NVIDIA GB300 (4 GPUs)"
|
||||
gpu_count: 4
|
||||
use_for: "Grace Blackwell next-gen AI"
|
||||
- name: BM.GPU.MI300X.8
|
||||
processor: "AMD Instinct MI300X (8 GPUs)"
|
||||
gpu_count: 8
|
||||
use_for: "AMD GPU AI/ML workloads"
|
||||
- name: BM.GPU.MI355X.8
|
||||
processor: "AMD Instinct MI355X (8 GPUs)"
|
||||
gpu_count: 8
|
||||
use_for: "AMD GPU next-gen AI/ML workloads"
|
||||
- name: BM.GPU.L40S.4
|
||||
processor: "NVIDIA L40S (4 GPUs)"
|
||||
gpu_count: 4
|
||||
use_for: "AI inference, graphics, video"
|
||||
|
||||
when_to_use:
|
||||
- Traditional VM-based applications
|
||||
|
||||
@@ -30,12 +30,14 @@ when_NOT_to_use:
|
||||
|
||||
limits:
|
||||
vm_shapes:
|
||||
- "VM.Standard.E5.Flex: 1-94 OCPUs"
|
||||
- "VM.Standard.E5.Flex: 1-64 OCPUs"
|
||||
- "VM.Standard3.Flex: 1-32 OCPUs"
|
||||
- "VM.Standard.x86: ECPU billing (new shape)"
|
||||
bm_shapes:
|
||||
- "BM.Standard.E5: 128 OCPUs"
|
||||
- "BM.DenseIO.E5: 128 OCPUs with NVMe"
|
||||
max_storage_tb: 80 # block storage
|
||||
max_storage_tb: 150 # block storage (Universal Credits)
|
||||
supported_versions: ["19c", "21c", "23ai", "26ai"]
|
||||
rac_max_nodes: 2
|
||||
|
||||
features:
|
||||
|
||||
@@ -27,15 +27,18 @@ limits:
|
||||
- name: "Exadata.Quarter3.100"
|
||||
base_ocpu: 100
|
||||
max_ocpu: 100
|
||||
storage_tb: 49.5
|
||||
storage_tb: 149
|
||||
notes: "Legacy X8 fixed shape — storage is usable disk"
|
||||
- name: "Exadata.Half3.200"
|
||||
base_ocpu: 200
|
||||
max_ocpu: 200
|
||||
storage_tb: 99
|
||||
storage_tb: 299
|
||||
notes: "Legacy X8 fixed shape"
|
||||
- name: "Exadata.Full3.400"
|
||||
base_ocpu: 400
|
||||
max_ocpu: 400
|
||||
storage_tb: 198
|
||||
storage_tb: 598
|
||||
notes: "Legacy X8 fixed shape; current generation is elastic X9M/X11M"
|
||||
max_vm_clusters: 8
|
||||
max_databases_per_cluster: "Limited by resources"
|
||||
max_pdb_per_cdb: 252
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# OCI Service: Exadata Cloud Service (ExaCS)
|
||||
# Last verified: 2026-03
|
||||
# Last verified: 2026-04
|
||||
|
||||
service:
|
||||
name: "Exadata Cloud Service (ExaCS)"
|
||||
@@ -26,32 +26,122 @@ variants:
|
||||
- id: exacs_x9m
|
||||
name: "ExaCS X9M"
|
||||
description: "Exadata X9M shape — current-generation infrastructure with RDMA over Converged Ethernet and persistent memory acceleration."
|
||||
- id: exacs_x10m
|
||||
name: "ExaCS X10M"
|
||||
description: "Exadata X10M shape — next-generation infrastructure with improved compute, storage density, and throughput."
|
||||
per_db_server:
|
||||
ocpus: 126
|
||||
memory_gb: 1390
|
||||
pmem_tb: 1.5
|
||||
flash_cache_tb: 25.6
|
||||
per_storage_server:
|
||||
usable_tb: 63.6
|
||||
- id: exacs_x11m
|
||||
name: "ExaCS X11M"
|
||||
description: "Exadata X11M shape — latest generation with AMD EPYC processors and XRMEM acceleration. Two storage server variants: HC (default, capacity-optimised) and EF (Extreme Flash, latency-optimised)."
|
||||
per_db_server:
|
||||
ecpus: 760
|
||||
memory_gb: 1390
|
||||
xrmem_gb: 1250
|
||||
flash_cache_tb: 27.2
|
||||
cpu: "2 × AMD EPYC 9J25 (96 cores each, 192 cores per server)"
|
||||
storage_server_variants:
|
||||
hc:
|
||||
name: "X11M High Capacity (HC)"
|
||||
description: "Default storage variant. 12 × 22 TB SAS HDDs + 27.2 TB flash cache + 1.25 TB XRMEM per SS. Best $/TB; same hot-data latency as EF (served from flash cache + XRMEM)."
|
||||
raw_tb_per_ss: 264
|
||||
flash_cache_tb_per_ss: 27.2
|
||||
xrmem_tb_per_ss: 1.25
|
||||
usable_disk_tb_per_ss: 80 # Datasheet "Total Usable Disk Capacity" per SS — post HIGH redundancy + drive-failure reserve, before compression
|
||||
max_db_size_tb_per_ss_no_local_backup: 64 # Derived: 192 TB / 3 SS at base config (datasheet Elastic Example 1)
|
||||
max_db_size_tb_per_ss_with_local_backup: 32 # Derived: 96 TB / 3 SS at base config
|
||||
total_cores_per_ss: 64
|
||||
recommended_for: "OLTP, mixed workloads, DWH where active set fits in flash cache (~80% of cases)"
|
||||
ef:
|
||||
name: "X11M Extreme Flash (EF)"
|
||||
description: "All-flash storage variant. Lower latency on cache-miss reads, but higher $/TB. Use when the working set exceeds flash cache or for latency-sensitive DWH full scans."
|
||||
usable_tb_per_ss: 52.5
|
||||
type: "Extreme Flash (EF)"
|
||||
recommended_for: "Latency-sensitive DWH with large full-table scans that miss flash cache; sub-ms consistent latency requirements"
|
||||
pricing_2026_04:
|
||||
source: "OCI Cost Estimator 2026-04-23"
|
||||
db_server_per_hour_usd: 2.9032
|
||||
storage_server_per_hour_usd: 2.9032
|
||||
base_config_monthly_usd: 10800 # (2 DB + 3 SS) × $2.9032 × 744 hr; excludes DB licenses (BYOL) and ECPU charges
|
||||
|
||||
sizing:
|
||||
rack_configurations:
|
||||
model: "Elastic per-server (X9M+: 2-32 DB servers, 3-64 storage servers). 'Quarter/half/full rack' terminology is legacy; X9M and X11M are billed per-server."
|
||||
notes: |
|
||||
Three different storage figures appear in Oracle datasheets — they measure different things:
|
||||
• Total Usable Disk Capacity = ASM-allocatable space, post HIGH redundancy + drive-failure reserve, before compression
|
||||
• Max DB Size – No Local Backup = practical limit for DB allocation after RECO/SPARSE/DBFS reserves (this is what OCI Cost Estimator caps at)
|
||||
• Max DB Size – With Local Backup = ~half of above (FRA on disk for backups)
|
||||
Always quote both Usable Disk and Max DB Size to avoid customer confusion.
|
||||
OCI scales storage by adding individual storage servers, not in racks.
|
||||
|
||||
base_configuration:
|
||||
description: "Minimum elastic configuration — what you get on day-1 before scaling."
|
||||
db_servers: 2
|
||||
storage_servers: 3
|
||||
|
||||
x11m_elastic_base:
|
||||
description: "Datasheet 'Elastic Configuration Example 1' (2 DB + 3 SS, all-elastic SKUs)."
|
||||
source: "ADB-D X11M Datasheet v1.0, Jan 2025, Table 1"
|
||||
db_servers: 2
|
||||
storage_servers: 3
|
||||
total_ecpus: 1520 # 2 × 760
|
||||
total_memory_gb: 2780 # 2 × 1,390
|
||||
total_xrmem_tb: 3.75 # 3 × 1.25 (XRMEM lives on storage servers)
|
||||
total_flash_tb: 81.6 # 3 × 27.2
|
||||
hc_variant:
|
||||
total_usable_disk_tb: 240 # Datasheet authoritative
|
||||
max_db_size_no_local_backup_tb: 192 # OCI Cost Estimator caps allocation here
|
||||
max_db_size_with_local_backup_tb: 96
|
||||
max_sql_flash_bandwidth_gbps: 300
|
||||
max_sql_xrmem_bandwidth_gbps: 1500
|
||||
max_sql_disk_bandwidth_gbps: 5.4
|
||||
max_sql_read_iops: 5_600_000
|
||||
max_sql_write_iops: 3_000_000
|
||||
max_sql_disk_iops: 7_800
|
||||
max_data_load_rate_tb_per_hr: 7.5
|
||||
ef_variant:
|
||||
usable_tb: 157.5 # 3 × 52.5
|
||||
sample_elastic_growth_examples:
|
||||
compute_heavy: { db_servers: 8, storage_servers: 8, total_ecpus: 6080, max_db_size_tb: 512 }
|
||||
storage_heavy: { db_servers: 2, storage_servers: 14, total_ecpus: 1520, max_db_size_tb: 896 }
|
||||
|
||||
x11m_base_system:
|
||||
description: "Hardware-generation-agnostic 'Base System' SKU — fixed-spec, NOT expandable, single VM Cluster only. Different product from elastic; entry-price option for small footprints."
|
||||
source: "ADB-D X11M Datasheet v1.0, Jan 2025, Table 1, footnote 1"
|
||||
db_servers: 2
|
||||
storage_servers: 3
|
||||
total_ecpus: 192
|
||||
total_memory_gb: 720
|
||||
total_flash_tb: 38.4
|
||||
total_usable_disk_tb: 73
|
||||
max_db_size_no_local_backup_tb: 58
|
||||
max_db_size_with_local_backup_tb: 29
|
||||
network: "10 GbE (vs 50 GbE on elastic)"
|
||||
notes: "Base System is NOT the same as 'Elastic Example 1 with 2 DB + 3 SS'. The elastic config has ~8× more ECPUs, ~4× more memory, ~3× more storage at same physical-server count, and 50 GbE networking. Base System is for cost-optimised entry; if customer expects to scale, go elastic from day 1."
|
||||
|
||||
x9m_base:
|
||||
cpu_ocpus: 252 # 2 × 126
|
||||
memory_tb: 2.71 # 2 × 1,390 GB
|
||||
pmem_tb: 3.0 # 2 × 1.5 (persistent memory tier)
|
||||
flash_cache_tb_db: 51.2 # 2 × 25.6
|
||||
hc_variant:
|
||||
usable_tb_per_ss: 63.6
|
||||
base_usable_tb_high_redundancy: 190.8 # 3 × 63.6
|
||||
notes: "X9M HC drives are 14 TB (vs 22 TB on X11M)."
|
||||
|
||||
legacy_x8_fixed_shapes:
|
||||
quarter_rack:
|
||||
ocpus: "100 (scalable)"
|
||||
memory: "1.44 TB"
|
||||
storage: "Up to 76.8 TB usable (Exadata Storage)"
|
||||
db_nodes: 2
|
||||
storage_servers: 3
|
||||
storage_tb: 149
|
||||
half_rack:
|
||||
ocpus: "200 (scalable)"
|
||||
memory: "2.88 TB"
|
||||
storage: "Up to 153.6 TB usable"
|
||||
db_nodes: 4
|
||||
storage_servers: 6
|
||||
storage_tb: 299
|
||||
full_rack:
|
||||
ocpus: "400 (scalable)"
|
||||
memory: "5.76 TB"
|
||||
storage: "Up to 307.2 TB usable"
|
||||
db_nodes: 8
|
||||
storage_servers: 12
|
||||
ocpu_scaling: "OCPUs can be scaled online in increments without downtime. You pay for enabled OCPUs, not the total available in the rack."
|
||||
sizing_guidance: "Start with a quarter rack for most production workloads. Scale OCPUs on demand. Choose half/full rack only when storage capacity or aggregate memory requirements exceed quarter rack limits."
|
||||
storage_tb: 598
|
||||
notes: "X8 shapes are fixed-size (not elastic). Storage values are usable disk, not flash cache."
|
||||
|
||||
ocpu_scaling: "OCPUs/ECPUs can be scaled online in increments without downtime. You pay for enabled cores, not the total available in the rack."
|
||||
sizing_guidance: "Start with the elastic base (2 DB + 3 SS) for most production workloads. Add storage servers when capacity or IOPS exceed base. Add DB servers when CPU saturates. Choose HC over EF unless workload is latency-sensitive on cache-miss reads."
|
||||
|
||||
gotchas:
|
||||
- id: exacs_minimum_cost
|
||||
@@ -78,6 +168,10 @@ gotchas:
|
||||
severity: LOW
|
||||
description: "ExaCS requires placement in a private subnet with sufficient IP addresses. Each DB node and each virtual IP consumes an IP; plan your subnet CIDR accordingly."
|
||||
|
||||
- id: exacs_x11m_hc_vs_ef
|
||||
severity: MEDIUM
|
||||
description: "X11M ships in two storage variants — HC (default, 264 TB raw / SS) and EF (all-flash, 52.5 TB usable / SS). Most customers should choose HC: same hot-data latency (served from 27.2 TB flash cache per SS) at far better $/TB. Only pick EF when the working set genuinely exceeds flash cache and you need sub-ms consistent latency on cache-miss reads. Many quotes default to EF without justification — confirm with the customer."
|
||||
|
||||
implied_dependencies:
|
||||
- service: vcn
|
||||
reason: "ExaCS infrastructure must be deployed in a VCN"
|
||||
@@ -99,3 +193,9 @@ changelog:
|
||||
- date: "2026-03-14"
|
||||
contributor: { name: "Diego Cabrera", team: "Field Architecture" }
|
||||
change: "Initial creation with shapes, sizing, gotchas, dependencies"
|
||||
- date: "2026-04-23"
|
||||
contributor: { name: "Diego Velásquez", team: "Field Architecture" }
|
||||
change: "Added X11M HC variant (default) alongside existing EF; replaced misleading rack_configurations table that mixed X9M data with elastic per-server model; added X11M and X9M base configs; added pricing verified against OCI Cost Estimator (DB+SS @ $2.9032/hr); added gotcha on HC vs EF default choice."
|
||||
- date: "2026-04-23"
|
||||
contributor: { name: "Diego Velásquez", team: "Field Architecture" }
|
||||
change: "Replaced earlier estimator-derived storage figures (63 TB/SS, 190 TB at base) with authoritative numbers from ADB-D X11M Datasheet v1.0 Jan 2025 Table 1. X11M HC SS = 80 TB Total Usable Disk (HIGH redundancy + drive-failure reserve). 3-SS Elastic base = 240 TB Total Usable Disk OR 192 TB Max DB Size (no local backup, what the Estimator caps at) OR 96 TB Max DB Size (with local backup). Also added separate Base System SKU (fixed, non-expandable, 73 TB usable disk) — distinct product from elastic 2 DB + 3 SS. Added performance metrics (IOPS, GB/s) for elastic base."
|
||||
|
||||
@@ -22,6 +22,7 @@ components:
|
||||
recommendation: "Prefer NSGs (Network Security Groups) for granular control"
|
||||
nsg:
|
||||
what: "Network Security Group — firewall rules at VNIC level"
|
||||
max_rules: "120 (ingress + egress combined per NSG)"
|
||||
recommendation: "Preferred over security lists for micro-segmentation"
|
||||
internet_gateway:
|
||||
what: "Enables internet access for public subnets"
|
||||
@@ -45,7 +46,7 @@ components:
|
||||
connectivity:
|
||||
fastconnect:
|
||||
what: "Dedicated private connection to OCI (like AWS Direct Connect)"
|
||||
speeds: ["1 Gbps", "2 Gbps", "5 Gbps", "10 Gbps", "100 Gbps"]
|
||||
speeds: ["1 Gbps", "2 Gbps", "5 Gbps", "10 Gbps", "100 Gbps", "400 Gbps"]
|
||||
redundancy: "Always deploy 2 circuits for HA"
|
||||
notes: "Partner or co-location model, typical setup takes 2-4 weeks"
|
||||
ipsec_vpn:
|
||||
|
||||
@@ -22,8 +22,9 @@ services:
|
||||
iops_per_gb: 75
|
||||
throughput_kbps_per_gb: 600
|
||||
- name: Ultra High Performance
|
||||
max_iops: 450000
|
||||
max_iops: 300000
|
||||
max_throughput_mbps: 2680
|
||||
notes: "IOPS range 75K-300K at 30-120 VPU"
|
||||
max_volume_size_tb: 32
|
||||
max_volumes_per_instance: 32
|
||||
|
||||
@@ -36,7 +37,7 @@ services:
|
||||
use_for: "Data accessed less than once per month"
|
||||
- name: Archive
|
||||
use_for: "Long-term retention, compliance"
|
||||
retrieval_time: "1 hour (standard), 1 minute (expedited)"
|
||||
retrieval_time: "1 hour (standard)"
|
||||
features:
|
||||
- "S3-compatible API"
|
||||
- "Versioning"
|
||||
@@ -49,7 +50,7 @@ services:
|
||||
what: "NFSv3-compatible managed file system"
|
||||
use_for: "Shared file access across multiple compute instances"
|
||||
max_size: "8 EB (exabytes)"
|
||||
iops: "Up to 25,000 IOPS per file system"
|
||||
iops: "Up to 50,000 IOPS per file system"
|
||||
throughput: "Up to 1.2 GB/s per mount target"
|
||||
|
||||
pricing:
|
||||
|
||||
@@ -4,9 +4,10 @@ description: ADB-S auto-scaling behavior, timing, and sizing implications.
|
||||
---
|
||||
|
||||
auto_scaling:
|
||||
notes: "OCPU is legacy billing. ECPU is now default. 1 OCPU ≈ 4 ECPUs."
|
||||
ocpu_scaling:
|
||||
trigger: "CPU demand exceeds current allocation"
|
||||
max_scale: "3x base OCPUs (up to 128 OCPU maximum)"
|
||||
max_scale: "3x base OCPUs/ECPUs (up to 128 OCPU / 512 ECPU maximum)"
|
||||
ramp_up_time: "2-3 minutes to begin scaling"
|
||||
ramp_down_time: "After sustained low utilization (5-10 minutes)"
|
||||
billing: "Only billed during active scaling period, per OCPU per second"
|
||||
|
||||
@@ -65,8 +65,8 @@ adb_s_sizing:
|
||||
memory_sizing:
|
||||
oci_shapes:
|
||||
standard_e4: "16 GB per OCPU (VM.Standard.E4.Flex)"
|
||||
standard_e5: "16 GB per OCPU (VM.Standard.E5.Flex)"
|
||||
standard_e5: "up to 64 GB per OCPU (VM.Standard.E5.Flex, default 16)"
|
||||
standard_a1: "6 GB per OCPU (VM.Standard.A1.Flex / Ampere)"
|
||||
standard_a2: "8 GB per OCPU (VM.Standard.A2.Flex / Ampere)"
|
||||
standard_a2: "up to 64 GB per OCPU (VM.Standard.A2.Flex / Ampere)"
|
||||
optimized3: "14 GB per OCPU (VM.Optimized3.Flex)"
|
||||
dense_io_e4: "32 GB per OCPU + local NVMe (VM.DenseIO.E4.Flex)"
|
||||
|
||||
@@ -21,18 +21,19 @@ block_volume:
|
||||
|
||||
- name: "Higher Performance"
|
||||
iops_per_gb: 75
|
||||
max_iops: 35000
|
||||
max_iops: 50000
|
||||
throughput_mbps_per_gb: 0.6
|
||||
max_throughput_mbps: 480
|
||||
max_throughput_mbps: 680
|
||||
use_when: "Database data files, high-throughput applications"
|
||||
|
||||
- name: "Ultra High Performance"
|
||||
iops_per_gb: 90
|
||||
max_iops: 120000
|
||||
max_iops: 300000
|
||||
iops_range: "75,000 - 300,000 (at 30-120 VPU)"
|
||||
throughput_mbps_per_gb: 0.72
|
||||
max_throughput_mbps: 2680
|
||||
use_when: "Extreme IOPS requirements, OLTP databases"
|
||||
notes: "Only available with certain compute shapes"
|
||||
notes: "Only available with certain compute shapes. IOPS scales with VPU (30-120)."
|
||||
|
||||
sizing_guidance: |
|
||||
1. Determine required IOPS (from AWR, CloudWatch, or application benchmarks)
|
||||
|
||||
@@ -33,14 +33,14 @@ storage_tiers:
|
||||
block_volume_higher_performance:
|
||||
type: "Block Volume (Higher Performance)"
|
||||
iops_per_gb: 75
|
||||
max_iops: 35000
|
||||
max_iops: 50000
|
||||
throughput_kbps_per_gb: 600
|
||||
max_throughput_mbps: 600
|
||||
max_throughput_mbps: 680
|
||||
latency_us: "Sub-millisecond"
|
||||
|
||||
block_volume_uhp:
|
||||
type: "Block Volume (Ultra High Performance)"
|
||||
max_iops: 450000
|
||||
max_iops: 300000
|
||||
max_throughput_mbps: 2680
|
||||
notes: "Requires UHP-enabled shapes"
|
||||
|
||||
@@ -53,7 +53,7 @@ storage_tiers:
|
||||
|
||||
file_storage:
|
||||
type: "File Storage (NFS)"
|
||||
max_iops: 25000
|
||||
max_iops: 50000
|
||||
max_throughput_mbps: 1200
|
||||
latency: "Sub-millisecond"
|
||||
use_for: "Shared file access, NFS workloads"
|
||||
|
||||
82
scripts/sync-skill.py
Normal file
82
scripts/sync-skill.py
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Sync SKILL.md (root, source of truth) to .agents/skills/oci-deal-accelerator/SKILL.md.
|
||||
|
||||
The Codex copy under .agents/ must be byte-identical to the root SKILL.md
|
||||
except for an auto-generated banner inserted after the YAML frontmatter.
|
||||
|
||||
Usage:
|
||||
python scripts/sync-skill.py # write the .agents/ copy
|
||||
python scripts/sync-skill.py --check # exit 1 if out of sync (for CI/lint)
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
SOURCE = os.path.join(PROJECT_ROOT, "SKILL.md")
|
||||
TARGET = os.path.join(
|
||||
PROJECT_ROOT, ".agents", "skills", "oci-deal-accelerator", "SKILL.md"
|
||||
)
|
||||
|
||||
BANNER = (
|
||||
"<!-- AUTO-GENERATED FROM /SKILL.md — do not edit directly. "
|
||||
"Run `python scripts/sync-skill.py` to regenerate. -->\n"
|
||||
)
|
||||
|
||||
|
||||
def render() -> str:
|
||||
"""Read root SKILL.md and return the .agents/ version with banner injected."""
|
||||
with open(SOURCE, "r", encoding="utf-8") as fh:
|
||||
content = fh.read()
|
||||
|
||||
# Inject banner after the closing `---` of the YAML frontmatter, if present.
|
||||
if content.startswith("---\n"):
|
||||
end = content.find("\n---\n", 4)
|
||||
if end != -1:
|
||||
head = content[: end + len("\n---\n")]
|
||||
tail = content[end + len("\n---\n") :]
|
||||
return head + "\n" + BANNER + tail
|
||||
|
||||
# No frontmatter — prepend banner.
|
||||
return BANNER + content
|
||||
|
||||
|
||||
def cmd_check() -> int:
|
||||
expected = render()
|
||||
if not os.path.isfile(TARGET):
|
||||
print(f"sync-skill: target missing: {TARGET}")
|
||||
return 1
|
||||
with open(TARGET, "r", encoding="utf-8") as fh:
|
||||
actual = fh.read()
|
||||
if actual == expected:
|
||||
print("sync-skill: OK (in sync)")
|
||||
return 0
|
||||
print("sync-skill: OUT OF SYNC")
|
||||
print(f" source: {SOURCE}")
|
||||
print(f" target: {TARGET}")
|
||||
print(" run: python scripts/sync-skill.py")
|
||||
return 1
|
||||
|
||||
|
||||
def cmd_write() -> int:
|
||||
expected = render()
|
||||
os.makedirs(os.path.dirname(TARGET), exist_ok=True)
|
||||
with open(TARGET, "w", encoding="utf-8") as fh:
|
||||
fh.write(expected)
|
||||
print(f"sync-skill: wrote {os.path.relpath(TARGET, PROJECT_ROOT)} "
|
||||
f"({len(expected.splitlines())} lines)")
|
||||
return 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Sync root SKILL.md to .agents/")
|
||||
parser.add_argument("--check", action="store_true",
|
||||
help="Exit 1 if out of sync; do not write.")
|
||||
args = parser.parse_args()
|
||||
return cmd_check() if args.check else cmd_write()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -371,8 +371,8 @@ def main():
|
||||
)
|
||||
parser.add_argument(
|
||||
"--profile",
|
||||
required=True,
|
||||
help="Path to workload profile YAML",
|
||||
default=None,
|
||||
help="Path to workload profile YAML (optional; defaults to minimal profile)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--architecture",
|
||||
@@ -381,8 +381,8 @@ def main():
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output",
|
||||
default="scorecard-output.yaml",
|
||||
help="Output scorecard file path",
|
||||
default=None,
|
||||
help="Output scorecard file path (default: print to stdout)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--format",
|
||||
@@ -393,7 +393,15 @@ def main():
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
profile = load_yaml(args.profile)
|
||||
if args.profile:
|
||||
profile = load_yaml(args.profile)
|
||||
else:
|
||||
profile = {
|
||||
"workload_profile": {
|
||||
"flags": {},
|
||||
"business_context": {"customer_name": "Unknown"},
|
||||
}
|
||||
}
|
||||
architecture = load_yaml(args.architecture)
|
||||
|
||||
customer = (
|
||||
@@ -414,23 +422,26 @@ def main():
|
||||
else:
|
||||
output = yaml.dump(scorecard, default_flow_style=False, sort_keys=False)
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
f.write(output)
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
f.write(output)
|
||||
|
||||
# Print summary
|
||||
sc = scorecard["well_architected_scorecard"]
|
||||
print(f"\nOCI Well-Architected Scorecard")
|
||||
print(f"{'=' * 50}")
|
||||
print(f"Overall Status: {sc['overall_status']}")
|
||||
print(f"Checks: {sc['summary']['total_passed']}/{sc['summary']['total_checks']} passed")
|
||||
print(f"Gaps: {sc['summary']['total_gaps']} "
|
||||
f"(HIGH: {sc['summary']['high_severity_gaps']}, "
|
||||
f"MEDIUM: {sc['summary']['medium_severity_gaps']}, "
|
||||
f"LOW: {sc['summary']['low_severity_gaps']})")
|
||||
print(f"\nPillar Results:")
|
||||
for pid, p in sc["pillars"].items():
|
||||
print(f" {pid}: {p['status']} ({p['checks_passed']}/{p['checks_total']})")
|
||||
print(f"\nScorecard written to: {args.output}")
|
||||
# Print summary to terminal when output goes to file
|
||||
sc = scorecard["well_architected_scorecard"]
|
||||
print(f"\nOCI Well-Architected Scorecard")
|
||||
print(f"{'=' * 50}")
|
||||
print(f"Overall Status: {sc['overall_status']}")
|
||||
print(f"Checks: {sc['summary']['total_passed']}/{sc['summary']['total_checks']} passed")
|
||||
print(f"Gaps: {sc['summary']['total_gaps']} "
|
||||
f"(HIGH: {sc['summary']['high_severity_gaps']}, "
|
||||
f"MEDIUM: {sc['summary']['medium_severity_gaps']}, "
|
||||
f"LOW: {sc['summary']['low_severity_gaps']})")
|
||||
print(f"\nPillar Results:")
|
||||
for pid, p in sc["pillars"].items():
|
||||
print(f" {pid}: {p['status']} ({p['checks_passed']}/{p['checks_total']})")
|
||||
print(f"\nScorecard written to: {args.output}")
|
||||
else:
|
||||
print(output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
184
scripts/validate-diagram.py
Normal file
184
scripts/validate-diagram.py
Normal file
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Diagram quality validator — checks generated .drawio files against
|
||||
Oracle Architecture Center visual standards.
|
||||
|
||||
Usage:
|
||||
python3 scripts/validate-diagram.py examples/output-demo-pharma-mx/opt02-architecture.drawio
|
||||
"""
|
||||
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
MIN_ICON_H = 45 # Minimum icon height (px) — Oracle refs use 50-60
|
||||
MIN_ICON_W = 30 # Minimum icon width (px)
|
||||
MAX_EMPTY_RATIO = 0.7 # Max empty space ratio in a container
|
||||
MIN_LABEL_FONT = 10 # Minimum label font size
|
||||
MIN_GAP_PX = 5 # Minimum gap between sibling elements
|
||||
|
||||
|
||||
def validate(filepath: str) -> list:
|
||||
"""Return list of (severity, message) tuples."""
|
||||
issues = []
|
||||
tree = ET.parse(filepath)
|
||||
root = tree.getroot()
|
||||
|
||||
icon_groups = []
|
||||
containers = []
|
||||
all_cells = {}
|
||||
|
||||
for cell in root.iter('mxCell'):
|
||||
cid = cell.get('id', '')
|
||||
style = cell.get('style', '')
|
||||
value = cell.get('value', '')
|
||||
geo = cell.find('mxGeometry')
|
||||
all_cells[cid] = cell
|
||||
|
||||
if geo is None:
|
||||
continue
|
||||
|
||||
w = float(geo.get('width', 0))
|
||||
h = float(geo.get('height', 0))
|
||||
x = float(geo.get('x', 0))
|
||||
y = float(geo.get('y', 0))
|
||||
|
||||
# Icon groups
|
||||
if 'group' in style and 'connectable=1' in style:
|
||||
icon_groups.append({
|
||||
'id': cid, 'x': x, 'y': y, 'w': w, 'h': h,
|
||||
'parent': cell.get('parent', ''),
|
||||
})
|
||||
if h < MIN_ICON_H:
|
||||
issues.append(('WARN', f'Icon {cid} too short: {h:.0f}px (min {MIN_ICON_H})'))
|
||||
if w < MIN_ICON_W:
|
||||
issues.append(('WARN', f'Icon {cid} too narrow: {w:.0f}px (min {MIN_ICON_W})'))
|
||||
|
||||
# Containers (regions, VCNs, subnets)
|
||||
if value and any(kw in value for kw in ['Region', 'VCN', 'Subnet', 'Oracle Cloud']):
|
||||
containers.append({
|
||||
'id': cid, 'name': value[:40], 'x': x, 'y': y, 'w': w, 'h': h,
|
||||
'parent': cell.get('parent', ''),
|
||||
})
|
||||
|
||||
# Check children overflow parents
|
||||
container_map = {}
|
||||
for cell in root.iter('mxCell'):
|
||||
cid = cell.get('id', '')
|
||||
val = cell.get('value', '')
|
||||
geo = cell.find('mxGeometry')
|
||||
if geo is not None and val:
|
||||
container_map[cid] = {
|
||||
'name': val[:50], 'x': float(geo.get('x', 0)),
|
||||
'y': float(geo.get('y', 0)), 'w': float(geo.get('width', 0)),
|
||||
'h': float(geo.get('height', 0)), 'parent': cell.get('parent', ''),
|
||||
}
|
||||
|
||||
for cid, c in container_map.items():
|
||||
parent = container_map.get(c['parent'])
|
||||
if parent:
|
||||
child_right = c['x'] + c['w']
|
||||
child_bottom = c['y'] + c['h']
|
||||
overflow_r = child_right - parent['w']
|
||||
overflow_b = child_bottom - parent['h']
|
||||
if overflow_r > 2:
|
||||
issues.append(('ERROR', f'{c["name"]} overflows {parent["name"]} RIGHT by {overflow_r:.0f}px'))
|
||||
if overflow_b > 2:
|
||||
issues.append(('ERROR', f'{c["name"]} overflows {parent["name"]} BOTTOM by {overflow_b:.0f}px'))
|
||||
|
||||
# Check for overlapping siblings (same parent)
|
||||
by_parent = {}
|
||||
for ig in icon_groups:
|
||||
by_parent.setdefault(ig['parent'], []).append(ig)
|
||||
|
||||
for parent_id, siblings in by_parent.items():
|
||||
siblings.sort(key=lambda s: (s['y'], s['x']))
|
||||
for i in range(len(siblings) - 1):
|
||||
a = siblings[i]
|
||||
b = siblings[i + 1]
|
||||
# Check vertical overlap (same column, x ranges overlap)
|
||||
x_overlap = not (a['x'] + a['w'] < b['x'] or b['x'] + b['w'] < a['x'])
|
||||
if x_overlap:
|
||||
gap = b['y'] - (a['y'] + a['h'])
|
||||
if gap < MIN_GAP_PX:
|
||||
issues.append(('ERROR', f'Overlap between icons in parent {parent_id}: gap={gap:.0f}px'))
|
||||
|
||||
# Check container utilization (warn on mostly empty containers)
|
||||
for cont in containers:
|
||||
children_area = 0
|
||||
for ig in icon_groups:
|
||||
if ig['parent'] == cont['id']:
|
||||
children_area += ig['w'] * ig['h']
|
||||
for child_cont in containers:
|
||||
if child_cont['parent'] == cont['id']:
|
||||
children_area += child_cont['w'] * child_cont['h']
|
||||
cont_area = cont['w'] * cont['h']
|
||||
if cont_area > 0:
|
||||
fill_ratio = children_area / cont_area
|
||||
if fill_ratio < (1 - MAX_EMPTY_RATIO):
|
||||
issues.append(('INFO', f'{cont["name"]}: {fill_ratio:.0%} filled ({cont["w"]:.0f}x{cont["h"]:.0f})'))
|
||||
|
||||
# Check edge labels have offset (mxPoint as="offset")
|
||||
edges_with_label = 0
|
||||
edges_with_offset = 0
|
||||
for cell in root.iter('mxCell'):
|
||||
if cell.get('edge') == '1' and cell.get('value', '').strip():
|
||||
edges_with_label += 1
|
||||
geo = cell.find('mxGeometry')
|
||||
if geo is not None:
|
||||
offset = geo.find('.//mxPoint[@as="offset"]')
|
||||
if offset is not None:
|
||||
edges_with_offset += 1
|
||||
|
||||
if edges_with_label > 0 and edges_with_offset < edges_with_label:
|
||||
issues.append(('WARN', f'{edges_with_label - edges_with_offset}/{edges_with_label} edge labels missing offset'))
|
||||
|
||||
# Check jettySize=auto present
|
||||
has_jetty = False
|
||||
for cell in root.iter('mxCell'):
|
||||
if 'jettySize=auto' in cell.get('style', ''):
|
||||
has_jetty = True
|
||||
break
|
||||
if not has_jetty:
|
||||
issues.append(('WARN', 'No edges with jettySize=auto'))
|
||||
|
||||
# Check container=1 present
|
||||
has_container = False
|
||||
for cell in root.iter('mxCell'):
|
||||
if 'container=1' in cell.get('style', ''):
|
||||
has_container = True
|
||||
break
|
||||
if not has_container:
|
||||
issues.append(('WARN', 'No containers with explicit container=1 style'))
|
||||
|
||||
return issues
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: {sys.argv[0]} <diagram.drawio>")
|
||||
sys.exit(1)
|
||||
|
||||
filepath = sys.argv[1]
|
||||
issues = validate(filepath)
|
||||
|
||||
if not issues:
|
||||
print(f"✅ {filepath}: All checks passed")
|
||||
sys.exit(0)
|
||||
|
||||
errors = [i for i in issues if i[0] == 'ERROR']
|
||||
warns = [i for i in issues if i[0] == 'WARN']
|
||||
infos = [i for i in issues if i[0] == 'INFO']
|
||||
|
||||
print(f"📋 Diagram validation: {filepath}")
|
||||
print(f" {len(errors)} errors, {len(warns)} warnings, {len(infos)} info")
|
||||
print()
|
||||
|
||||
for severity, msg in issues:
|
||||
icon = {'ERROR': '❌', 'WARN': '⚠️', 'INFO': 'ℹ️'}.get(severity, '?')
|
||||
print(f" {icon} [{severity}] {msg}")
|
||||
|
||||
sys.exit(1 if errors else 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
BIN
templates/Oracle_PPT-template_FY26.pptx
Normal file
BIN
templates/Oracle_PPT-template_FY26.pptx
Normal file
Binary file not shown.
51
templates/bom-spec.yaml
Normal file
51
templates/bom-spec.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
# ──────────────────────────────────────────────────────────────────
|
||||
# OCI Bill of Materials (BOM) — Spec Template
|
||||
# ──────────────────────────────────────────────────────────────────
|
||||
# The AI generates this YAML based on the customer's request,
|
||||
# selecting only the relevant SKUs from kb/pricing/oci-sku-catalog.yaml.
|
||||
# The BOM generator tool (tools/oci_bom_gen.py) renders it to .xlsx.
|
||||
#
|
||||
# Usage:
|
||||
# python tools/oci_bom_gen.py --spec this-file.yaml --output bom.xlsx
|
||||
|
||||
bom:
|
||||
# ── Header ──────────────────────────────────────────────────────
|
||||
customer_name: ""
|
||||
project_name: ""
|
||||
prepared_by: ""
|
||||
date: "" # ISO format: 2026-03-27
|
||||
reference_label: "" # e.g., "ACME-BOM-001"
|
||||
currency: USD # Primary currency
|
||||
# realm: "OC1 - Commercial" # Optional: OC1 / OC2 / OC3 / OC9
|
||||
# service_type: "Pay as You Go" # Optional: PAYG / UCM / Annual Flex
|
||||
|
||||
# ── Optional currency conversion ────────────────────────────────
|
||||
# Enable to add converted columns (e.g., USD → BRL with tax)
|
||||
conversion:
|
||||
enabled: false
|
||||
target_currency: BRL
|
||||
exchange_rate: 5.75 # 1 USD = X target currency
|
||||
tax_rate: 0.0 # e.g., 0.1385 for 13.85% ISS+PIS+COFINS
|
||||
|
||||
# ── Line items (only requested services) ────────────────────────
|
||||
# Each item must reference a SKU from oci-sku-catalog.yaml.
|
||||
# Only include services the customer actually needs.
|
||||
line_items:
|
||||
- sku: "B97384" # Must match oci-sku-catalog.yaml
|
||||
qty: 4 # Number of instances/units
|
||||
# hours_units: 730 # Override catalog default if needed
|
||||
months: 12 # Contract duration
|
||||
discount: 0.0 # 0.0 to 1.0 (e.g., 0.30 = 30%)
|
||||
# custom_label: "" # Optional label
|
||||
# custom_note: "" # Optional note
|
||||
|
||||
- sku: "B97385"
|
||||
qty: 64 # 64 GB memory
|
||||
months: 12
|
||||
discount: 0.0
|
||||
|
||||
# ── Notes (optional) ────────────────────────────────────────────
|
||||
notes:
|
||||
- "Pricing based on Ashburn region (OC1)"
|
||||
- "Discounts subject to Oracle approval"
|
||||
- "Hours convention — 730 vs 744: this BOM uses 730 hrs/month (= 8,760 annual hrs / 12), which equals the actual yearly OCI billing for hourly SKUs. OCI Cost Estimator defaults to 744 hrs/month (worst-case 31-day month); extrapolated to 12 months, 744 overstates the real annual cost by 1.92%. For 12-month TCO/proposals, 730 is the accurate figure; 744 is only appropriate when quoting a single peak month as an upper bound."
|
||||
@@ -151,12 +151,13 @@ class TestKBLinter:
|
||||
# (like 'cli', 'maintenance-window', etc.)
|
||||
|
||||
def test_owner_check(self):
|
||||
"""Owner check returns issues for TBD owners."""
|
||||
"""Owner check returns a list and matches the current owners config."""
|
||||
issues = kb_linter.check_owners()
|
||||
assert isinstance(issues, list)
|
||||
# We know some owners are TBD
|
||||
tbd_issues = [i for i in issues if "TBD" in i]
|
||||
assert len(tbd_issues) > 0, "Expected TBD owner issues"
|
||||
# Current config may be fully assigned; if issues exist they should be
|
||||
# the explicit TBD-owner messages emitted by the linter.
|
||||
for issue in issues:
|
||||
assert "TBD" in issue
|
||||
|
||||
def test_freshness_check(self):
|
||||
"""Freshness check returns a list of file freshness reports."""
|
||||
@@ -207,34 +208,44 @@ class TestKBCLI:
|
||||
# Service changelog tests
|
||||
# ---------------------------------------------------------------------------
|
||||
class TestServiceChangelogs:
|
||||
"""Verify that service files have changelog sections."""
|
||||
"""Verify that service files load correctly and validate changelogs when present."""
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def service_files(self):
|
||||
services_dir = KB_DIR / "services"
|
||||
return list(services_dir.glob("*.yaml"))
|
||||
|
||||
@staticmethod
|
||||
def _load_service_yaml(filepath):
|
||||
merged = {}
|
||||
with open(filepath, "r", encoding="utf-8") as fh:
|
||||
for doc in yaml.safe_load_all(fh):
|
||||
if isinstance(doc, dict):
|
||||
merged.update(doc)
|
||||
return merged
|
||||
|
||||
def test_service_files_exist(self, service_files):
|
||||
assert len(service_files) > 0
|
||||
|
||||
def test_service_files_have_changelog(self, service_files):
|
||||
"""Each service file should have a changelog section."""
|
||||
def test_service_files_load_as_merged_documents(self, service_files):
|
||||
"""Service files may be multi-document YAML and should load via safe_load_all."""
|
||||
for filepath in service_files:
|
||||
with open(filepath, "r") as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
assert "changelog" in data, (
|
||||
f"Service file '{filepath.name}' missing 'changelog' section"
|
||||
)
|
||||
assert len(data["changelog"]) > 0, (
|
||||
f"Service file '{filepath.name}' has empty changelog"
|
||||
data = self._load_service_yaml(filepath)
|
||||
assert isinstance(data, dict), f"Service file '{filepath.name}' did not merge into a dict"
|
||||
assert any(key in data for key in ("service", "description", "swagger_ui", "kb_target_file")), (
|
||||
f"Service file '{filepath.name}' is missing an identifying top-level key"
|
||||
)
|
||||
|
||||
def test_changelog_entries_have_required_fields(self, service_files):
|
||||
"""Changelog entries must have date, contributor, change."""
|
||||
"""Changelog entries must have date, contributor, change when a changelog exists."""
|
||||
changelog_files = 0
|
||||
for filepath in service_files:
|
||||
with open(filepath, "r") as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
data = self._load_service_yaml(filepath)
|
||||
if "changelog" not in data:
|
||||
continue
|
||||
changelog_files += 1
|
||||
for entry in data.get("changelog", []):
|
||||
assert "date" in entry, f"Changelog entry in {filepath.name} missing 'date'"
|
||||
assert "contributor" in entry, f"Changelog entry in {filepath.name} missing 'contributor'"
|
||||
assert "change" in entry, f"Changelog entry in {filepath.name} missing 'change'"
|
||||
assert changelog_files > 0, "Expected at least one service file with changelog entries"
|
||||
|
||||
83
tests/test_oci_bizcase_gen_input_aliases.py
Normal file
83
tests/test_oci_bizcase_gen_input_aliases.py
Normal file
@@ -0,0 +1,83 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
TOOLS_DIR = PROJECT_ROOT / "tools"
|
||||
|
||||
if str(TOOLS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(TOOLS_DIR))
|
||||
|
||||
from oci_bizcase_gen import BusinessCaseDeckGenerator
|
||||
|
||||
|
||||
def _collect_slide_text(gen):
|
||||
texts = []
|
||||
for slide in gen.prs.slides:
|
||||
for shape in slide.shapes:
|
||||
if hasattr(shape, "text"):
|
||||
text = shape.text.strip()
|
||||
if text:
|
||||
texts.append(text)
|
||||
if getattr(shape, "has_table", False):
|
||||
for row in shape.table.rows:
|
||||
for cell in row.cells:
|
||||
text = cell.text.strip()
|
||||
if text:
|
||||
texts.append(text)
|
||||
return "\n".join(texts)
|
||||
|
||||
|
||||
def test_from_spec_accepts_cover_aliases_and_recommendation_fallback():
|
||||
spec = {
|
||||
"customer": "Acme Corp",
|
||||
"author": "Diego",
|
||||
"generated_on": "2026-04-21",
|
||||
"recommendation": {
|
||||
"commitment_amount": "100K",
|
||||
"commitment_type": "UCM",
|
||||
},
|
||||
}
|
||||
|
||||
gen = BusinessCaseDeckGenerator.from_spec(spec)
|
||||
text = _collect_slide_text(gen)
|
||||
|
||||
assert "Acme Corp" in text
|
||||
assert "Prepared by: Diego" in text
|
||||
assert "Recommended: 100K UCM commitment" in text
|
||||
|
||||
|
||||
def test_from_spec_accepts_roadmap_aliases_and_mixed_next_steps():
|
||||
spec = {
|
||||
"customer_name": "Acme Corp",
|
||||
"roadmap": {
|
||||
"phases": [
|
||||
{
|
||||
"title": "Assess",
|
||||
"weeks": "2 weeks",
|
||||
"outputs": ["Blueprint"],
|
||||
"milestones": ["Kickoff"],
|
||||
}
|
||||
],
|
||||
"total_duration": "6 weeks",
|
||||
},
|
||||
"recommendation": {
|
||||
"summary": "Proceed with phased migration",
|
||||
"next_steps": [
|
||||
"Confirm scope",
|
||||
{"action": "Approve budget", "owner": "Finance", "deadline": "May"},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
gen = BusinessCaseDeckGenerator.from_spec(spec)
|
||||
text = _collect_slide_text(gen)
|
||||
|
||||
assert "Assess" in text
|
||||
assert "2 weeks" in text
|
||||
assert "Kickoff" in text
|
||||
assert "Blueprint" in text
|
||||
assert "Confirm scope" in text
|
||||
assert "Approve budget" in text
|
||||
assert "Finance" in text
|
||||
assert "May" in text
|
||||
80
tests/test_oci_bom_gen_input_aliases.py
Normal file
80
tests/test_oci_bom_gen_input_aliases.py
Normal file
@@ -0,0 +1,80 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
TOOLS_DIR = PROJECT_ROOT / "tools"
|
||||
|
||||
if str(TOOLS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(TOOLS_DIR))
|
||||
|
||||
from oci_bom_gen import OCIBomGenerator
|
||||
|
||||
|
||||
def test_from_spec_accepts_metadata_and_line_item_aliases():
|
||||
spec = {
|
||||
"customer": "Acme Corp",
|
||||
"project": "Database Migration",
|
||||
"author": "Diego",
|
||||
"reference": "REF-1",
|
||||
"conversion": {
|
||||
"currency": "BRL",
|
||||
"exchange_rate": 5.2,
|
||||
"tax_rate": 0.1,
|
||||
},
|
||||
"line_items": [
|
||||
{
|
||||
"part_number": "SKU-001",
|
||||
"quantity": 2,
|
||||
"units": 730,
|
||||
"discount_pct": 15,
|
||||
"label": "Database",
|
||||
"note": "Primary environment",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
gen = OCIBomGenerator.from_spec(spec)
|
||||
item = gen.line_items[0]
|
||||
|
||||
assert gen.customer == "Acme Corp"
|
||||
assert gen.project == "Database Migration"
|
||||
assert gen.prepared_by == "Diego"
|
||||
assert gen.reference_label == "REF-1"
|
||||
assert gen.conversion["target_currency"] == "BRL"
|
||||
assert item["sku"] == "SKU-001"
|
||||
assert item["qty"] == 2
|
||||
assert item["hours_units"] == 730
|
||||
assert item["discount"] == 15
|
||||
assert item["custom_label"] == "Database"
|
||||
assert item["custom_note"] == "Primary environment"
|
||||
|
||||
|
||||
def test_from_spec_accepts_canonical_sku_and_custom_note():
|
||||
spec = {
|
||||
"line_items": [
|
||||
{
|
||||
"sku": "SKU-002",
|
||||
"qty": 1,
|
||||
"hours_units": 100,
|
||||
"custom_note": "Canonical form",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
gen = OCIBomGenerator.from_spec(spec)
|
||||
item = gen.line_items[0]
|
||||
|
||||
assert item["sku"] == "SKU-002"
|
||||
assert item["qty"] == 1
|
||||
assert item["hours_units"] == 100
|
||||
assert item["custom_note"] == "Canonical form"
|
||||
|
||||
|
||||
def test_from_spec_requires_sku_or_part_number():
|
||||
spec = {"line_items": [{"quantity": 1}]}
|
||||
|
||||
with pytest.raises(ValueError, match="sku"):
|
||||
OCIBomGenerator.from_spec(spec)
|
||||
98
tests/test_oci_deck_gen_input_aliases.py
Normal file
98
tests/test_oci_deck_gen_input_aliases.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
TOOLS_DIR = PROJECT_ROOT / "tools"
|
||||
|
||||
if str(TOOLS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(TOOLS_DIR))
|
||||
|
||||
from oci_deck_gen import OCIDeckGenerator
|
||||
|
||||
|
||||
def _collect_slide_text(gen):
|
||||
texts = []
|
||||
for slide in gen.prs.slides:
|
||||
for shape in slide.shapes:
|
||||
if hasattr(shape, "text"):
|
||||
text = shape.text.strip()
|
||||
if text:
|
||||
texts.append(text)
|
||||
if getattr(shape, "has_table", False):
|
||||
for row in shape.table.rows:
|
||||
for cell in row.cells:
|
||||
text = cell.text.strip()
|
||||
if text:
|
||||
texts.append(text)
|
||||
return "\n".join(texts)
|
||||
|
||||
|
||||
def test_from_spec_accepts_metadata_aliases_and_current_state_string():
|
||||
spec = {
|
||||
"metadata": {
|
||||
"customer_name": "Acme Corp",
|
||||
"project_name": "DB Migration",
|
||||
"prepared_by": "Diego",
|
||||
"title": "Target Architecture",
|
||||
},
|
||||
"summary": {
|
||||
"why": "Modernize platform",
|
||||
"current_state": "Legacy estate",
|
||||
"target_state": "OCI landing zone",
|
||||
"timeline": "Q3",
|
||||
},
|
||||
}
|
||||
|
||||
gen = OCIDeckGenerator.from_spec(spec)
|
||||
text = _collect_slide_text(gen)
|
||||
|
||||
assert gen.customer == "Acme Corp"
|
||||
assert gen.project == "DB Migration"
|
||||
assert gen.architect == "Diego"
|
||||
assert "Legacy estate" in text
|
||||
assert "OCI landing zone" in text
|
||||
|
||||
|
||||
def test_from_spec_accepts_aliases_for_cost_migration_risk_scorecard_and_next_steps():
|
||||
spec = {
|
||||
"metadata": {"customer": "Acme"},
|
||||
"cost": {
|
||||
"line_items": [
|
||||
{"name": "DB Service", "monthly": "USD 100", "note": "Includes storage"}
|
||||
],
|
||||
"assumptions": ["1 region"],
|
||||
"show_byol": False,
|
||||
},
|
||||
"migration": {
|
||||
"phases": [
|
||||
{"title": "Discover", "weeks": "2 weeks", "tasks": ["Inventory", "Assess"]}
|
||||
],
|
||||
"tools": ["ZDM"],
|
||||
"downtime": "Near-zero",
|
||||
},
|
||||
"risks": [
|
||||
{"title": "Cutover risk", "action": "Pilot first", "severity": "high"}
|
||||
],
|
||||
"scorecard": {
|
||||
"pillars": [
|
||||
{"pillar": "Security", "status": "PASS", "passed": 2, "total": 2}
|
||||
],
|
||||
"recommendations": ["Enable auditing"],
|
||||
},
|
||||
"next_steps": {"next_steps": ["Validate scope"]},
|
||||
}
|
||||
|
||||
gen = OCIDeckGenerator.from_spec(spec)
|
||||
text = _collect_slide_text(gen)
|
||||
|
||||
assert "DB Service" in text
|
||||
assert "USD 100" in text
|
||||
assert "Includes storage" in text
|
||||
assert "Discover" in text
|
||||
assert "Inventory" in text
|
||||
assert "Cutover risk" in text
|
||||
assert "Pilot first" in text
|
||||
assert "Security" in text
|
||||
assert "2/2" in text
|
||||
assert "Validate scope" in text
|
||||
76
tests/test_oci_diagram_gen_input_aliases.py
Normal file
76
tests/test_oci_diagram_gen_input_aliases.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
TOOLS_DIR = PROJECT_ROOT / "tools"
|
||||
|
||||
if str(TOOLS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(TOOLS_DIR))
|
||||
|
||||
from oci_diagram_gen import OCIDiagramGenerator
|
||||
|
||||
|
||||
def test_from_spec_accepts_name_aliases_and_generates_ids():
|
||||
spec = {
|
||||
"external": [{"name": "Users"}],
|
||||
"clouds": [{"name": "AWS", "services": [{"name": "EC2 App", "service_type": "ec2"}]}],
|
||||
"tenancy": {
|
||||
"regions": [
|
||||
{
|
||||
"name": "Ashburn",
|
||||
"vcns": [
|
||||
{
|
||||
"name": "App VCN",
|
||||
"subnets": [
|
||||
{"name": "App Subnet", "services": [{"name": "App VM"}]}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
"on_prem": {"name": "Primary DC", "services": [{"name": "Legacy DB"}]},
|
||||
}
|
||||
|
||||
gen = OCIDiagramGenerator.from_spec(spec)
|
||||
values = [getattr(obj, "value", "") for obj in gen._objects.values()]
|
||||
|
||||
assert "Users" in values
|
||||
assert "AWS" in values
|
||||
assert "Ashburn" in values
|
||||
assert "VCN App VCN" in values
|
||||
assert "App Subnet" in values
|
||||
assert "App VM" in values
|
||||
assert "Primary DC" in values
|
||||
assert "Legacy DB" in values
|
||||
|
||||
|
||||
def test_from_spec_accepts_source_target_and_omits_unresolved_connections():
|
||||
spec = {
|
||||
"external": [{"name": "Users"}],
|
||||
"tenancy": {
|
||||
"regions": [
|
||||
{
|
||||
"name": "Ashburn",
|
||||
"vcns": [
|
||||
{
|
||||
"name": "App VCN",
|
||||
"subnets": [
|
||||
{"name": "App Subnet", "services": [{"name": "App VM"}]}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": [
|
||||
{"source": "Users", "target": "App VM", "type": "standard", "label": "HTTPS"},
|
||||
{"from": "Users", "to": "App VM", "type": "standard", "label": "Duplicate"},
|
||||
{"source": "Users", "target": "Missing VM", "type": "standard", "label": "Broken"},
|
||||
],
|
||||
}
|
||||
|
||||
gen = OCIDiagramGenerator.from_spec(spec)
|
||||
|
||||
assert gen._connection_count == 1
|
||||
@@ -28,6 +28,7 @@ Usage:
|
||||
|
||||
import argparse
|
||||
import difflib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from collections import Counter
|
||||
@@ -378,6 +379,10 @@ def cmd_list(args: argparse.Namespace) -> None:
|
||||
category=getattr(args, "category", None),
|
||||
)
|
||||
|
||||
if getattr(args, "json_output", False):
|
||||
print(json.dumps(results, indent=2, default=str))
|
||||
return
|
||||
|
||||
if not results:
|
||||
print("No findings match the given filters.")
|
||||
return
|
||||
@@ -401,6 +406,21 @@ def cmd_search(args: argparse.Namespace) -> None:
|
||||
"""Full-text search."""
|
||||
results = search(args.query)
|
||||
|
||||
# Apply optional filters (mirrors list subcommand)
|
||||
results = filter_findings(
|
||||
results,
|
||||
severity=getattr(args, "severity", None),
|
||||
product=getattr(args, "product", None),
|
||||
tag=getattr(args, "tag", None),
|
||||
client=getattr(args, "client", None),
|
||||
status=getattr(args, "status", None),
|
||||
category=getattr(args, "category", None),
|
||||
)
|
||||
|
||||
if getattr(args, "json_output", False):
|
||||
print(json.dumps(results, indent=2, default=str))
|
||||
return
|
||||
|
||||
if not results:
|
||||
print(f"No findings matching '{args.query}'.")
|
||||
return
|
||||
@@ -600,6 +620,10 @@ def cmd_stats(args: argparse.Namespace) -> None:
|
||||
"""Display summary statistics."""
|
||||
s = stats()
|
||||
|
||||
if getattr(args, "json_output", False):
|
||||
print(json.dumps(s, indent=2))
|
||||
return
|
||||
|
||||
print(f"Total findings: {s['total']}\n")
|
||||
|
||||
print("By Severity:")
|
||||
@@ -640,10 +664,18 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
p_list.add_argument("--client", help="Filter by client (partial match).")
|
||||
p_list.add_argument("--status", help="Filter by status.")
|
||||
p_list.add_argument("--category", help="Filter by category.")
|
||||
p_list.add_argument("--json", action="store_true", dest="json_output", help="Output as JSON.")
|
||||
|
||||
# --- search ---
|
||||
p_search = subparsers.add_parser("search", help="Full-text search.")
|
||||
p_search.add_argument("query", help="Search term.")
|
||||
p_search.add_argument("--severity", help="Filter by severity.")
|
||||
p_search.add_argument("--product", help="Filter by product (partial match).")
|
||||
p_search.add_argument("--tag", help="Filter by tag.")
|
||||
p_search.add_argument("--client", help="Filter by client (partial match).")
|
||||
p_search.add_argument("--status", help="Filter by status.")
|
||||
p_search.add_argument("--category", help="Filter by category.")
|
||||
p_search.add_argument("--json", action="store_true", dest="json_output", help="Output as JSON.")
|
||||
|
||||
# --- add ---
|
||||
p_add = subparsers.add_parser("add", help="Add a new finding.")
|
||||
@@ -685,7 +717,8 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
subparsers.add_parser("aer", help="After-Engagement Review (interactive).")
|
||||
|
||||
# --- stats ---
|
||||
subparsers.add_parser("stats", help="Show summary statistics.")
|
||||
p_stats = subparsers.add_parser("stats", help="Show summary statistics.")
|
||||
p_stats.add_argument("--json", action="store_true", dest="json_output", help="Output as JSON.")
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
475
tools/gen_demo_deck.py
Normal file
475
tools/gen_demo_deck.py
Normal file
@@ -0,0 +1,475 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
OCI Deal Accelerator — Demo Presentation Generator
|
||||
|
||||
10-minute technical demo deck: AI-powered SA workflow acceleration.
|
||||
Uses Oracle FY26 template via OraclePresBase.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
from pptx.util import Inches, Pt
|
||||
from pptx.dml.color import RGBColor
|
||||
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
|
||||
from pptx.enum.shapes import MSO_SHAPE
|
||||
|
||||
from oci_pptx_base import Colors, Layouts, OraclePresBase
|
||||
|
||||
|
||||
class DemoDeckGenerator(OraclePresBase):
|
||||
TITLE_ACCENT_COLOR = Colors.TEAL
|
||||
MARGIN = Inches(0.5)
|
||||
SLIDE_WIDTH = Inches(13.333)
|
||||
|
||||
def add_cover(self):
|
||||
"""Slide 1: Cover — dark, high impact."""
|
||||
slide = self._add_layout_slide(Layouts.COVER_DARK)
|
||||
self._set_placeholder(slide, 0, "OCI Deal Accelerator")
|
||||
self._set_placeholder(slide, 1,
|
||||
"AI-Powered Architecture Proposals in Hours, Not Days")
|
||||
return slide
|
||||
|
||||
def add_impact_slide(self, metric, statement, detail=""):
|
||||
"""Big metric slide — dark background, single number."""
|
||||
slide = self._add_layout_slide(Layouts.IMPACT_DARK)
|
||||
self._set_placeholder(slide, 0, metric)
|
||||
self._set_placeholder(slide, 1, statement)
|
||||
if detail:
|
||||
self._set_placeholder(slide, 37, detail)
|
||||
return slide
|
||||
|
||||
def add_content_slide(self, title, bullets, note=""):
|
||||
"""Standard content slide with title bar + bullet list."""
|
||||
slide = self._add_blank_slide()
|
||||
self._add_title_bar(slide, title, margin=self.MARGIN)
|
||||
|
||||
y = Inches(1.4)
|
||||
txBox = self._add_textbox(
|
||||
slide, self.MARGIN + Inches(0.1), y,
|
||||
Inches(12), Inches(5),
|
||||
text="", font_size=15,
|
||||
)
|
||||
tf = txBox.text_frame
|
||||
tf.word_wrap = True
|
||||
# First paragraph already exists
|
||||
tf.paragraphs[0].text = bullets[0] if bullets else ""
|
||||
tf.paragraphs[0].font.size = Pt(15)
|
||||
tf.paragraphs[0].font.name = self.FONT
|
||||
tf.paragraphs[0].font.color.rgb = Colors.PRIMARY_TEXT
|
||||
tf.paragraphs[0].space_after = Pt(6)
|
||||
|
||||
for b in bullets[1:]:
|
||||
self._add_paragraph(tf, b, font_size=15, space_after=6)
|
||||
|
||||
if note:
|
||||
self._add_textbox(
|
||||
slide, self.MARGIN, Inches(6.5),
|
||||
Inches(12), Inches(0.5),
|
||||
text=note, font_size=11, italic=True,
|
||||
color=Colors.SECONDARY_TEXT,
|
||||
)
|
||||
return slide
|
||||
|
||||
def add_prompt_table_slide(self, title, rows):
|
||||
"""Slide with a table of option # | prompt example."""
|
||||
slide = self._add_blank_slide()
|
||||
self._add_title_bar(slide, title, margin=self.MARGIN)
|
||||
|
||||
n = len(rows) + 1
|
||||
row_h = min(0.52, 5.2 / max(n, 1))
|
||||
table = self._add_table(
|
||||
slide, n, 3,
|
||||
self.MARGIN, Inches(1.3),
|
||||
Inches(12.3), Inches(row_h * n),
|
||||
)
|
||||
table.columns[0].width = Inches(0.6)
|
||||
table.columns[1].width = Inches(3.0)
|
||||
table.columns[2].width = Inches(8.7)
|
||||
|
||||
for j, h in enumerate(["#", "Capability", "Live Prompt"]):
|
||||
self._style_table_cell(
|
||||
table.cell(0, j), h, font_size=10, bold=True,
|
||||
color=Colors.WHITE, bg_color=Colors.TEAL,
|
||||
alignment=PP_ALIGN.CENTER if j == 0 else PP_ALIGN.LEFT,
|
||||
)
|
||||
|
||||
for i, (num, cap, prompt) in enumerate(rows):
|
||||
ri = i + 1
|
||||
bg = Colors.TABLE_ALT_ROW if ri % 2 == 0 else None
|
||||
self._style_table_cell(table.cell(ri, 0), str(num), font_size=10,
|
||||
bold=True, bg_color=bg, alignment=PP_ALIGN.CENTER)
|
||||
self._style_table_cell(table.cell(ri, 1), cap, font_size=10,
|
||||
bold=True, bg_color=bg)
|
||||
self._style_table_cell(table.cell(ri, 2), prompt, font_size=9,
|
||||
bg_color=bg)
|
||||
|
||||
return slide
|
||||
|
||||
def add_before_after_slide(self):
|
||||
"""Before/After comparison slide."""
|
||||
slide = self._add_blank_slide()
|
||||
self._add_title_bar(slide, "Before vs After: SA Workflow", margin=self.MARGIN)
|
||||
|
||||
# BEFORE column
|
||||
self._add_rect(slide, self.MARGIN, Inches(1.4),
|
||||
Inches(5.8), Inches(0.5), fill_color=Colors.ORACLE_RED)
|
||||
self._add_textbox(slide, self.MARGIN + Inches(0.2), Inches(1.45),
|
||||
Inches(5.4), Inches(0.4),
|
||||
text="BEFORE — Manual SA Workflow",
|
||||
font_size=14, bold=True, color=Colors.WHITE)
|
||||
|
||||
before = [
|
||||
("Discovery call", "1h"),
|
||||
("Research services + sizing", "2-4h"),
|
||||
("Build architecture diagram", "1-2h"),
|
||||
("Write proposal deck", "3-5h"),
|
||||
("Cost estimate + BOM", "1-2h"),
|
||||
("WA review (if time permits)", "2-3h"),
|
||||
("Internal review + revisions", "1-2h"),
|
||||
("TOTAL", "11-19 hours (2-3 days)"),
|
||||
]
|
||||
|
||||
y = Inches(2.0)
|
||||
for task, time in before:
|
||||
bold = task == "TOTAL"
|
||||
color = Colors.ORACLE_RED if bold else Colors.PRIMARY_TEXT
|
||||
self._add_textbox(slide, Inches(0.7), y, Inches(3.8), Inches(0.32),
|
||||
text=task, font_size=11, bold=bold, color=color)
|
||||
self._add_textbox(slide, Inches(4.6), y, Inches(1.5), Inches(0.32),
|
||||
text=time, font_size=11, bold=bold, color=color,
|
||||
alignment=PP_ALIGN.RIGHT)
|
||||
y += Inches(0.35)
|
||||
|
||||
# AFTER column
|
||||
self._add_rect(slide, Inches(6.8), Inches(1.4),
|
||||
Inches(5.8), Inches(0.5), fill_color=Colors.FOREST)
|
||||
self._add_textbox(slide, Inches(7.0), Inches(1.45),
|
||||
Inches(5.4), Inches(0.4),
|
||||
text="AFTER — AI-Assisted Workflow",
|
||||
font_size=14, bold=True, color=Colors.WHITE)
|
||||
|
||||
after = [
|
||||
("Discovery call", "1h"),
|
||||
("Paste notes → Full proposal", "3-5 min"),
|
||||
("Architecture diagram", "included"),
|
||||
("Slide deck (18 slides)", "included"),
|
||||
("Cost estimate + BOM", "included"),
|
||||
("WA review (5-pillar)", "included"),
|
||||
("SA reviews AI output", "30-60 min"),
|
||||
("TOTAL", "1.5-2 hours (same day)"),
|
||||
]
|
||||
|
||||
y = Inches(2.0)
|
||||
for task, time in after:
|
||||
bold = task == "TOTAL"
|
||||
color = Colors.FOREST if bold else Colors.PRIMARY_TEXT
|
||||
self._add_textbox(slide, Inches(7.0), y, Inches(3.8), Inches(0.32),
|
||||
text=task, font_size=11, bold=bold, color=color)
|
||||
self._add_textbox(slide, Inches(11.0), y, Inches(1.5), Inches(0.32),
|
||||
text=time, font_size=11, bold=bold, color=color,
|
||||
alignment=PP_ALIGN.RIGHT)
|
||||
y += Inches(0.35)
|
||||
|
||||
# Savings callout
|
||||
self._add_rect(slide, Inches(3.5), Inches(5.3),
|
||||
Inches(6.3), Inches(0.7), fill_color=Colors.TEAL)
|
||||
self._add_textbox(slide, Inches(3.6), Inches(5.35),
|
||||
Inches(6.1), Inches(0.6),
|
||||
text="85% time reduction | Same day delivery | Higher quality (WA-validated)",
|
||||
font_size=14, bold=True, color=Colors.WHITE,
|
||||
alignment=PP_ALIGN.CENTER)
|
||||
|
||||
return slide
|
||||
|
||||
def add_comparison_table_slide(self, title, rows):
|
||||
"""Two-column comparison: Generic LLM vs This Skill."""
|
||||
slide = self._add_blank_slide()
|
||||
self._add_title_bar(slide, title, margin=self.MARGIN)
|
||||
|
||||
n = len(rows) + 1
|
||||
row_h = min(0.58, 5.0 / max(n, 1))
|
||||
table = self._add_table(
|
||||
slide, n, 3,
|
||||
self.MARGIN, Inches(1.35),
|
||||
Inches(12.3), Inches(row_h * n),
|
||||
)
|
||||
table.columns[0].width = Inches(2.8)
|
||||
table.columns[1].width = Inches(4.75)
|
||||
table.columns[2].width = Inches(4.75)
|
||||
|
||||
headers = ["", "Generic LLM (ChatGPT, etc.)", "OCI Deal Accelerator"]
|
||||
header_colors = [Colors.TEAL, Colors.ORACLE_RED, Colors.FOREST]
|
||||
for j, (h, hc) in enumerate(zip(headers, header_colors)):
|
||||
self._style_table_cell(
|
||||
table.cell(0, j), h, font_size=10, bold=True,
|
||||
color=Colors.WHITE, bg_color=hc,
|
||||
alignment=PP_ALIGN.CENTER,
|
||||
)
|
||||
|
||||
for i, (aspect, generic, skill) in enumerate(rows):
|
||||
ri = i + 1
|
||||
bg = Colors.TABLE_ALT_ROW if ri % 2 == 0 else None
|
||||
self._style_table_cell(table.cell(ri, 0), aspect, font_size=10,
|
||||
bold=True, bg_color=bg)
|
||||
self._style_table_cell(table.cell(ri, 1), generic, font_size=9,
|
||||
bg_color=bg)
|
||||
self._style_table_cell(table.cell(ri, 2), skill, font_size=9,
|
||||
bg_color=bg)
|
||||
|
||||
return slide
|
||||
|
||||
def add_divider(self, text):
|
||||
slide = self._add_layout_slide(Layouts.DIVIDER_DARK)
|
||||
self._set_placeholder(slide, 0, text)
|
||||
return slide
|
||||
|
||||
|
||||
def build_demo_deck(output_path):
|
||||
gen = DemoDeckGenerator()
|
||||
|
||||
# ── SLIDE 1: Cover (0:00-0:15) ──
|
||||
gen.add_cover()
|
||||
|
||||
# ── SLIDE 2: The Problem — impact (0:15-1:00) ──
|
||||
gen.add_impact_slide(
|
||||
"11-19h",
|
||||
"Time an SA spends per proposal",
|
||||
"Research + diagram + deck + costs + review — repeated for every deal"
|
||||
)
|
||||
|
||||
# ── SLIDE 3: The Aha Moment (1:00-2:00) ──
|
||||
gen.add_before_after_slide()
|
||||
|
||||
# ── SLIDE 4: Why Not Just Use ChatGPT? (2:00-3:30) ──
|
||||
gen.add_comparison_table_slide(
|
||||
'"Can\'t I Just Ask ChatGPT to Make Me a Deck?"',
|
||||
[
|
||||
("Pricing",
|
||||
"Training data from 2024. Invents SKUs. No discount calc. Can't generate a BOM.",
|
||||
"160+ SKUs auto-refreshed from Oracle API. Real PAYG/BYOL. BOM + AppCA export."),
|
||||
("Architecture",
|
||||
"Generic diagrams. Suggests services that don't exist or don't apply.",
|
||||
"Patterns from real deployments. Knows ExaCS needs 3+ storage for IORM."),
|
||||
("Field gotchas",
|
||||
"Doesn't know DEP takes 3 weeks to provision, or that ADG must be disabled first.",
|
||||
"8+ validated findings from real engagements, with workarounds and SR refs."),
|
||||
("Competitive",
|
||||
"Tends to be either biased or generic. No real cost comparison data.",
|
||||
"Honest pros/cons per service. BYOL 50-75% cheaper data. Knows where AWS wins."),
|
||||
("WA validation",
|
||||
"Gives generic 'best practices' list. No scoring, no gap analysis.",
|
||||
"80+ checks across 5 pillars. Automated scoring. Actionable gap report."),
|
||||
("Compliance",
|
||||
"Generic SOX/PCI advice. Doesn't know OCI-specific controls.",
|
||||
"OCI Vault for TDE, Unified Auditing, compartment isolation — mapped to frameworks."),
|
||||
("Output format",
|
||||
"Markdown or basic text. Manual copy-paste to slides.",
|
||||
"Oracle FY26 .pptx template, .drawio, branded .pdf, .xlsx — ready to present."),
|
||||
("Improves over time",
|
||||
"Frozen at training cutoff. Learns nothing from your engagements.",
|
||||
"Every SA adds findings. Pricing refreshes. KB compounds with every deal."),
|
||||
],
|
||||
)
|
||||
|
||||
# ── SLIDE 5: What Is It (3:30-4:00) ──
|
||||
gen.add_content_slide(
|
||||
"OCI Deal Accelerator — What Is It?",
|
||||
[
|
||||
"An AI skill (system prompt + knowledge base + tools) for any LLM with tool-use and 100K+ context",
|
||||
"Works on Claude, Codex, GPT, Gemini — any model that can read files + run Python",
|
||||
"The LLM is the engine. The KB + tools are the fuel. The SA is the driver.",
|
||||
"Aligned with ECAL framework: Define > Design > Deliver",
|
||||
"7 Python generators: .pptx, .drawio, .pdf, .xlsx, WA scorecard, BOM, AppCA",
|
||||
"14 capabilities accessible via natural language — not a chatbot, a domain-specific SA tool",
|
||||
],
|
||||
)
|
||||
|
||||
# ── SLIDE 6: Divider — Live Demo (4:00) ──
|
||||
gen.add_divider("Live Demo: 14 Capabilities")
|
||||
|
||||
# ── SLIDE 6: Prompts 1-7 (3:00-6:00) ──
|
||||
gen.add_prompt_table_slide(
|
||||
"Design, Validate & Compare (Options 1-7)",
|
||||
[
|
||||
("1", "Full proposal",
|
||||
"Cliente farmaceutico en Mexico, 3 Oracle DBs (EBS R12 prod, SAP, DW) en "
|
||||
"Exadata X6 on-prem. HW refresh vence en 6 meses. Quieren migrar a OCI, "
|
||||
"RPO<15min, RTO<1h, necesitan compliance SOX. 200 usuarios concurrentes, "
|
||||
"2TB data, pico en cierre fiscal. Budget: reducir 30% vs renovar HW."),
|
||||
("2", "Architecture diagram",
|
||||
"Diagrama: ExaCS en Queretaro (prod) + Standby con Data Guard en Sao Paulo, "
|
||||
"Hub-Spoke networking con DRG, FastConnect 10Gbps dual desde Mexico City, "
|
||||
"bastion en public subnet, WAF para apps web, Vault para TDE keys."),
|
||||
("3", "Slide deck",
|
||||
"Genera el deck para la propuesta del cliente farmaceutico."),
|
||||
("4", "Cost estimate",
|
||||
"ExaCS X11M Quarter Rack BYOL, 2 DB servers, 3 storage servers, "
|
||||
"400GB RAM, 10TB usable + ADB-S 16 ECPU + FastConnect 1Gbps dual + "
|
||||
"50TB Object Storage + OCI Vault. 12 meses, 40% descuento."),
|
||||
("5", "WA review",
|
||||
"Review: ADB-S 23ai en Sao Paulo region unica, IAM con admin por defecto, "
|
||||
"sin encryption at rest explicita, sin WAF, monitoring con scripts custom, "
|
||||
"patching manual mensual, backup solo local, sin network segmentation."),
|
||||
("6", "Feature check",
|
||||
"Does ADB-S Dedicated Elastic Pool support Auto Indexing on 23ai? "
|
||||
"And what about AI Vector Search with HNSW indexes at 100M+ vectors?"),
|
||||
("7", "Competitive",
|
||||
"Customer comparing ADB-S vs AWS Aurora PostgreSQL for a mixed OLTP+analytics "
|
||||
"workload, 500GB, needs partitioning, RAC equivalent, and BYOL licensing. "
|
||||
"They think Aurora is cheaper. Give me honest pros and cons."),
|
||||
],
|
||||
)
|
||||
|
||||
# ── SLIDE 7: Prompts 8-14 (6:00-8:30) ──
|
||||
gen.add_prompt_table_slide(
|
||||
"Strategy, KB, Governance & SA Tools (Options 8-14)",
|
||||
[
|
||||
("8", "Business case",
|
||||
"Business case: 5 Oracle DBs on-prem (EBS, Siebel, DW, 2 custom), "
|
||||
"$1.2M/yr infra (HW refresh vence Q3). CTO quiere cloud, CFO quiere "
|
||||
"numeros. Necesito TCO 3 anos, ROI, risk of doing nothing, y que pasa "
|
||||
"si renuevan HW por 5 anos mas. Audience: board de directores."),
|
||||
("9", "Field findings",
|
||||
"What real issues has the field team found with ADB-S Dedicated Elastic "
|
||||
"Pool? Include DEP provisioning times, maintenance windows, and ADG."),
|
||||
("10", "Reference arch",
|
||||
"Reference architectures for cross-region DR with Exadata and Data Guard. "
|
||||
"Need options for both ExaCS and ADB-S with automatic failover."),
|
||||
("11", "Report finding",
|
||||
"New finding: ExaCS iormcal fails silently when storage server count < 3. "
|
||||
"Product: ExaCS, Version: 23ai, Severity: MEDIUM, found during pharma "
|
||||
"engagement in Mexico. Workaround: validate IORM plan output after apply, "
|
||||
"check v$iorm_plans for actual vs requested shares."),
|
||||
("12", "ECAL readiness",
|
||||
"Score this engagement: tenemos discovery notes, workload profile, y un "
|
||||
"diagrama de arquitectura. No hay business case, no value story, no "
|
||||
"handover plan, no operations model. Customer es farmaceutica en Mexico, "
|
||||
"engagement tier standard, estamos en la fase Design."),
|
||||
("13", "BOM generator",
|
||||
"BOM: ExaCS X11M Half Rack BYOL, 4 DB servers 128 ECPUs each, "
|
||||
"6 storage servers, ADB-S 32 ECPU, 50TB block storage, "
|
||||
"FastConnect 10Gbps dual, OCI Vault, 12 months, 45% discount."),
|
||||
("14", "BOM for AppCA",
|
||||
"Same BOM as 13 but in AppCA import format for deal approval."),
|
||||
],
|
||||
)
|
||||
|
||||
# ── SLIDE 8: The KB Is the Moat (7:30-8:15) ──
|
||||
gen.add_content_slide(
|
||||
"The Knowledge Base Is the Moat",
|
||||
[
|
||||
"40+ YAML files of FIELD knowledge — not regurgitated docs, real experience",
|
||||
"Services: what each OCI service does, when to use it, gotchas, sizing rules",
|
||||
"Patterns: composable architecture blocks (HA, DR, networking, security baselines)",
|
||||
"Pricing: 160+ SKUs auto-refreshed from Oracle public API (refresh_sku_catalog.py)",
|
||||
"Field findings: production issues with workarounds, contributor attribution, confidence levels",
|
||||
"Competitive: honest AWS/Azure mapping with real advantage/disadvantage per service",
|
||||
"Architecture Center: 123 curated reference architectures with service + tag filtering",
|
||||
"",
|
||||
"Without the KB, the AI is just another chatbot. With it, it's a domain expert.",
|
||||
],
|
||||
)
|
||||
|
||||
# ── SLIDE 9: Auto-refresh + Collaborative Model (8:15-9:00) ──
|
||||
gen.add_content_slide(
|
||||
"Self-Updating KB + Collaborative Field Intelligence",
|
||||
[
|
||||
"AUTO-REFRESH — pricing stays current without manual intervention:",
|
||||
" python refresh_sku_catalog.py --refresh --diff # updates 160+ SKUs from Oracle API",
|
||||
" python refresh_arch_catalog.py --whats-new # crawls Architecture Center for new entries",
|
||||
"",
|
||||
"COLLABORATIVE — every SA contributes, everyone benefits:",
|
||||
" findings_cli.py add --product ExaCS --severity HIGH --summary '...'",
|
||||
" Each finding has: contributor, team, client, confidence, confirmations[]",
|
||||
" Other SAs can confirm: findings_cli.py confirm FF-202603-001 --name '...'",
|
||||
"",
|
||||
"GOVERNANCE — quality stays high as the KB grows:",
|
||||
" kb_cli.py health # freshness dashboard: 63 files, stale detection",
|
||||
" kb_cli.py stats stale # reports files older than review cadence",
|
||||
" Every file has last_verified date + domain owner in kb-owners.yaml",
|
||||
"",
|
||||
"The KB compounds: every engagement makes the next one faster and better.",
|
||||
],
|
||||
)
|
||||
|
||||
# ── SLIDE 10: MCP Server — Zero Setup (8:30-9:00) ──
|
||||
gen.add_content_slide(
|
||||
"MCP Server: Use It From Any Client — Zero Code Setup",
|
||||
[
|
||||
"The skill also runs as an MCP (Model Context Protocol) server.",
|
||||
"14 tools exposed over HTTP — same capabilities, no local repo needed.",
|
||||
"",
|
||||
"SUPPORTED CLIENTS — connect once, use forever:",
|
||||
" Claude Code / Claude Desktop (OAuth) | Cursor (OAuth)",
|
||||
" Codex - OpenAI (Bearer token) | Windsurf (SSE)",
|
||||
" Any MCP-compliant client",
|
||||
"",
|
||||
"SETUP — 1 command, done:",
|
||||
" claude mcp add --transport http oci-deal-accelerator \\",
|
||||
' "https://mcp.tech-lad.com/deal-accelerator/mcp/"',
|
||||
"",
|
||||
"HOW IT WORKS:",
|
||||
" Your IDE / Claude --> MCP Server (Docker) --> KB + Tools + Generators",
|
||||
" You type a prompt --> Server runs the tool --> You get .pptx, .xlsx, .json",
|
||||
"",
|
||||
"Zero Python setup. Zero repo cloning. Zero dependency management.",
|
||||
"The SA opens their IDE, connects to the MCP, and starts working.",
|
||||
],
|
||||
)
|
||||
|
||||
# ── SLIDE 11: Key Takeaways (9:00-9:30) ──
|
||||
gen.add_content_slide(
|
||||
"Key Takeaways",
|
||||
[
|
||||
"85% time reduction: from 2-3 days to 2 hours per proposal",
|
||||
"Higher quality: every proposal is WA-validated with 5-pillar scoring",
|
||||
"The KB is the moat: field experience > documentation > AI hallucination",
|
||||
"Self-updating: pricing + architectures refresh automatically",
|
||||
"Collaborative: every SA's gotcha becomes everyone's advantage",
|
||||
"MCP server: zero setup, use from any AI client (Claude, Codex, Cursor...)",
|
||||
"Real deliverables: .pptx, .drawio, .pdf, .xlsx, BOM, AppCA — not chat summaries",
|
||||
"SA stays in control: AI generates, architect reviews and refines",
|
||||
],
|
||||
)
|
||||
|
||||
# ── SLIDE 12: Get Started ──
|
||||
gen.add_content_slide(
|
||||
"Get Started Right Now",
|
||||
[
|
||||
"OPTION A — MCP Server (recommended, zero setup):",
|
||||
" claude mcp add --transport http oci-deal-accelerator \\",
|
||||
' "https://mcp.tech-lad.com/deal-accelerator/mcp/"',
|
||||
"",
|
||||
"OPTION B — Clone the skill repo (full access to KB + tools):",
|
||||
" git clone https://git.tech-lad.com.br/diegoecab/oci-deal-accelerator.git",
|
||||
"",
|
||||
"MCP Server repo (deploy your own instance):",
|
||||
" github.com/Diegoecab/arch-mcp-oracle",
|
||||
"",
|
||||
"Skill repo (KB + tools + generators):",
|
||||
" git.tech-lad.com.br/diegoecab/oci-deal-accelerator",
|
||||
"",
|
||||
"",
|
||||
"Skill repo: git.tech-lad.com.br/diegoecab/oci-deal-accelerator MCP repo: github.com/Diegoecab/arch-mcp-oracle",
|
||||
],
|
||||
note="Scan the QR or visit the link above to get started in 30 seconds"
|
||||
)
|
||||
|
||||
# ── SLIDE 13: Closing ──
|
||||
gen.add_closing_slide(
|
||||
name="OCI Deal Accelerator",
|
||||
title="git.tech-lad.com.br/diegoecab/oci-deal-accelerator | github.com/Diegoecab/arch-mcp-oracle",
|
||||
)
|
||||
|
||||
gen.save(output_path)
|
||||
print(f"Generated: {output_path}")
|
||||
print(f" Slides: {gen.slide_count}")
|
||||
print(f" Duration: ~10 minutes")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
out = sys.argv[1] if len(sys.argv) > 1 else "demo-presentation.pptx"
|
||||
build_demo_deck(out)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user