Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "Azure / AI / Regulatory Intelligence",
"build": {
"dockerfile": "../../03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence/.devcontainer/Dockerfile"
},
"features": {
"ghcr.io/devcontainers/features/azure-cli:1": {
"installBicep": true
},
"ghcr.io/azure/azure-dev/azd:latest": {}
},
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}/03-Azure/01-04-AI/11_Healthcare_Regulatory_Intelligence",
"remoteUser": "vscode",
"waitFor": "postCreateCommand",
"postCreateCommand": "uv sync --frozen --all-extras && uv run --frozen --all-extras pytest -q",
"forwardPorts": [
8088
],
"portsAttributes": {
"8088": {
"label": "Regulatory Intelligence Assistant (local run)",
"visibility": "private",
"onAutoForward": "notify"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-azuretools.vscode-bicep"
],
"settings": {
"python.defaultInterpreterPath": "/home/vscode/.venvs/regintel/bin/python",
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.pytestArgs": [
"tests"
],
"terminal.integrated.defaultProfile.linux": "bash",
"git.openRepositoryInParentFolders": "always"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM mcr.microsoft.com/devcontainers/python:1-3.12-bookworm

RUN python -m pip install --no-cache-dir \
--index-url https://packagefeedproxy.microsoft.io/pypi/simple/ uv==0.12.10

ENV UV_PROJECT_ENVIRONMENT=/home/vscode/.venvs/regintel \
UV_PYTHON_DOWNLOADS=never \
PATH="/home/vscode/.venvs/regintel/bin:${PATH}"

RUN mkdir -p /home/vscode/.venvs && chown vscode:vscode /home/vscode/.venvs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "Caldova Regulatory Intelligence",
"build": {
"dockerfile": "Dockerfile"
},
"features": {
"ghcr.io/devcontainers/features/azure-cli:1": {
"installBicep": true
},
"ghcr.io/azure/azure-dev/azd:latest": {}
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/regulatory-intelligence,type=bind,consistency=cached",
"workspaceFolder": "/workspaces/regulatory-intelligence",
"remoteUser": "vscode",
"waitFor": "postCreateCommand",
"postCreateCommand": "uv sync --frozen --all-extras && uv run --frozen --all-extras pytest -q",
"forwardPorts": [8088],
"portsAttributes": {
"8088": {
"label": "Regulatory Intelligence Assistant (local run)",
"visibility": "private",
"onAutoForward": "notify"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-azuretools.vscode-bicep"
],
"settings": {
"python.defaultInterpreterPath": "/home/vscode/.venvs/regintel/bin/python",
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.pytestArgs": ["tests"],
"terminal.integrated.defaultProfile.linux": "bash",
"git.openRepositoryInParentFolders": "always"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.venv
.git
.env
out
__pycache__
.pytest_cache
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
description: "Use when you want to validate that this hack is fully compliant with the microsoft/MicroHack platform conventions. Checks directory naming, deploy-lab.ps1 parameter contract, lab-defaults.json schema validity, platform integration rules (no Connect-AzAccount, no premature RG creation), credential return pattern, and content structure. Run before committing or requesting platform access."
name: "Hack Compliance Validator"
tools: [read, search]
user-invocable: true
argument-hint: "Validate this hack for EMEA platform compliance"
---

You are a strict EMEA MicroHack platform compliance auditor based on [microsoft/MicroHack](https://github.com/microsoft/MicroHack).
Inspect this workspace and produce a pass/fail report against every mandatory convention.

## Compliance Checklist

Work through each item. Mark ✅ PASS or ❌ FAIL with a brief reason.

### 1. Directory Structure
- [ ] `labautomation/` directory exists (no dashes; exactly `labautomation`).
- [ ] `labautomation/` contains **only** `deploy-lab.ps1`, `lab-defaults.json`, and `README.md`, with no stray files (facilitator notes, runbooks, secrets, etc.). One-time setup / prerequisite docs belong in `walkthrough/` or a separate top-level folder, not here.
- [ ] `labautomation/lab-defaults.json` exists.
- [ ] `labautomation/README.md` exists.
- [ ] A root readme exists **and its casing matches every link that targets it**. GitHub is case-sensitive: if files in `challenges/` or `walkthrough/` link to `../Readme.md`, the root file MUST be `Readme.md` (not `README.md`), and vice-versa. Flag any mismatch as **blocking**: the "Home" navigation links 404 on GitHub even though they resolve on Windows.
- [ ] `challenges/` directory exists.
- [ ] `walkthrough/` directory exists.

### 2. deploy-lab.ps1: Parameter Contract
- [ ] `labautomation/deploy-lab.ps1` exists (optional but recommended).
- [ ] If it exists: parameter block declares exactly `$DeploymentType`, `$SubscriptionId`, `$ResourceGroupName`, `$PreferredLocation`, `$AllowedEntraUserIds`.
- [ ] `$DeploymentType` has `[ValidateSet('subscription','resourcegroup','resourcegroup-with-subscriptionowner')]`.

### 3. deploy-lab.ps1: Platform Integration Rules
- [ ] Script does **NOT** call `Connect-AzAccount` (platform pre-sets Az context).
- [ ] For `resourcegroup` deployment type: script does **NOT** call `New-AzResourceGroup` (platform pre-creates it).
- [ ] For `subscription` deployment type: script uses `Get-MhhStableHash` to generate a deterministic RG name.
- [ ] Any `Get-MhhStableHash` call passes `-Length` within the valid **12–64** range. Values below 12 throw at runtime and silently fail the whole deployment. Flag as **blocking**.

### 4. deploy-lab.ps1: Credential Return
- [ ] Script emits at least one `@{ HackboxCredential = @{ name = ...; value = ...; note = ... } }` to the output stream.

### 5. lab-defaults.json: Schema Validity
- [ ] File is valid JSON (no comments, no trailing commas).
- [ ] Contains `"$schema"` pointing to the MicroHack schema URL.
- [ ] `deploymentType` is one of: `"resourcegroup"`, `"resourcegroup-with-subscriptionowner"`, `"subscription"`.
- [ ] `preferredLocation` is a comma-separated string of Azure region names.
- [ ] `estimatedDailyCostsUsd` is a non-negative number.

### 6. Platform Compatibility
- [ ] No hard-coded corporate network, specific DNS, or environment-specific blocks.
- [ ] Script works for on-site, online, and hybrid event formats.

---

## How to Run

1. Use `#tool:search` and `#tool:read` to locate and read each required file.
2. For each checklist item, read the relevant section and determine pass/fail.
3. Output the full checklist with ✅/❌ status.
4. Output a **Summary** section:
- Total: X/6 categories passing
- Blocking issues (❌ on categories 1–5 are blocking)
- Recommendations (non-blocking improvements)

Be strict. A missing `$schema` in lab-defaults.json or a wrong parameter name in deploy-lab.ps1 causes the platform to skip the script silently. Flag these as blocking. A root-readme casing mismatch and an out-of-range `Get-MhhStableHash -Length` are also blocking (broken GitHub links / runtime failure respectively).
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# MicroHack Lab: EMEA Platform Conventions

This workspace is a microhack lab for the **EMEA MicroHack platform** ([microsoft/MicroHack](https://github.com/microsoft/MicroHack)).
The platform renders a front-end UI, but **all resource provisioning comes from `labautomation/deploy-lab.ps1`**.
Without a working deployment script, no resources appear in the Azure portal; the platform is just a shiny front end.

## Mandatory Structure

```
labautomation/ ← exactly this name, no dashes
deploy-lab.ps1 ← platform entry point (optional but recommended)
lab-defaults.json ← platform configuration (required if folder exists)
README.md ← usage notes
challenges/ ← challenge instructions (Markdown)
walkthrough/ ← solutions
README.md ← hack intro, objectives, prerequisites
```

## deploy-lab.ps1: Parameter Contract

The platform **skips the script** if the parameter block does not exactly match:

```powershell
param(
[Parameter(Mandatory=$true)]
[ValidateSet('subscription','resourcegroup','resourcegroup-with-subscriptionowner')]
[string]$DeploymentType,

[Parameter(Mandatory=$true)]
[string]$SubscriptionId,

[string]$ResourceGroupName = "",

[string[]]$PreferredLocation = @(),

[string[]]$AllowedEntraUserIds = @()
)
```

## Platform Guarantees (before your script runs)

- Az context is already set to `$SubscriptionId`, so **do NOT call `Connect-AzAccount`**
- For `resourcegroup`/`resourcegroup-with-subscriptionowner`: the RG exists and your script has `Owner`, so **do NOT call `New-AzResourceGroup`**
- For `subscription`: your script has `Owner` on the subscription; **you must create the RG yourself** using `Get-MhhStableHash` for deterministic naming
- `Az.Accounts` and `Az.Resources` modules are already imported

## lab-defaults.json: Required Shape

```json
{
"$schema": "https://raw.githubusercontent.com/microsoft/MicroHack/refs/heads/main/lab-defaults-schema.json",
"groups": [],
"deploymentType": "resourcegroup",
"labsPerSubscription": 4,
"preferredLocation": "uksouth",
"estimatedDailyCostsUsd": 15.0
}
```

- `deploymentType`: `"resourcegroup"` | `"resourcegroup-with-subscriptionowner"` | `"subscription"`
- `groups`: `[]` (Azure only), `["GHCPUsers"]` (GitHub Copilot seat), `["M365-E5-Users"]` (M365 E5)
- `preferredLocation`: comma-separated regions, priority order
- `estimatedDailyCostsUsd`: per-user per-day cost for the lifecycle wizard

## Returning Credentials to Users

Write a hashtable to the output stream. The platform captures it and shows it on the user's dashboard:

```powershell
@{ HackboxCredential = @{ name = "ResourceGroupName"; value = $ResourceGroupName; note = "Dedicated training resources" } }
```

## Regulatory Intelligence Scope

This workspace is `11_Healthcare_Regulatory_Intelligence`.
Keep changes confined to this lab and its explicit catalogue link.

The storyline: Caldova Health Services Ltd, a fictional UK life-sciences company,
sells one medicine, Caldivex (tablets CDX-TAB, injection pen CDX-PEN). Keep the
cast that small: everyone else is a role (Labelling Lead, Quality Head, ...).
Do not frame the workshop as an adaptation of another MicroHack, and do not add
attribution sections.

The hack implements the healthcare and life sciences regulatory-intelligence case
overview: Regulatory Web & Change Monitor, Document & Citation Agent, Obligation &
Impact Extractor, Regulatory Q&A Assistant and Executive Briefing with human
sign-off. Participants build prompt agents in the Foundry portal over a Foundry IQ
knowledge base on the `regulatory-knowledge` Blob container.

Crawling, de-duplication, versioning and recording sign-off are deterministic code
in `regintel/` (Python standard library only, Python 3.9+ for Cloud Shell). Agents
read, link, explain and summarise; they propose, never approve. All publications,
products and dates are fictional. Keep `tests/` passing and update expected answers
in `walkthrough/` when the data in `data/` changes.

Keep infrastructure templates in `infra/`, not `labautomation/`. Do not add a
cross-region fallback without explicit approval.
## Platform Compatibility

The platform supports **on-site**, **online**, and **hybrid** delivery.
Do not hard-code corporate network or specific DNS assumptions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
description: "Use when creating, editing, or reviewing labautomation/deploy-lab.ps1, lab-defaults.json, or any PowerShell helper inside labautomation/. Enforces microsoft/MicroHack platform deployment conventions."
applyTo: "labautomation/**,**/11_Healthcare_Regulatory_Intelligence/labautomation/**"
---

# Lab Automation Conventions (microsoft/MicroHack)

## deploy-lab.ps1: Required Parameter Contract

The platform **silently skips** the script if the parameter block does not match exactly:

```powershell
param(
[Parameter(Mandatory=$true)]
[ValidateSet('subscription','resourcegroup','resourcegroup-with-subscriptionowner')]
[string]$DeploymentType,

[Parameter(Mandatory=$true)]
[string]$SubscriptionId,

[string]$ResourceGroupName = "",

[string[]]$PreferredLocation = @(),

[string[]]$AllowedEntraUserIds = @()
)
```

## Critical Platform Rules

**NEVER do these. They break platform integration:**

```powershell
# WRONG: platform already sets Az context
Connect-AzAccount

# WRONG: platform pre-creates the RG for resourcegroup deployments
New-AzResourceGroup -Name $ResourceGroupName ...
```

**For `subscription` deployments only**, you must create your own RG using a deterministic name:

```powershell
$stableHash = Get-MhhStableHash $AllowedEntraUserIds -Length 24
$effectiveResourceGroup = "lab-$stableHash"
New-AzResourceGroup -Name $effectiveResourceGroup -Location $effectiveLocation
```

## Resolving Effective Location

```powershell
$effectiveLocation = if ($PreferredLocation.Count -eq 1) { $PreferredLocation[0] } else { "swedencentral" }
```

Reject more than one preferred region in this lab. Do not silently move resources
or processing across borders. Surface capacity/availability failures for facilitator approval.

## Deploying Resources

Reference templates relative to `$scriptPath`:

```powershell
$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$template = Join-Path $scriptPath "..\infra\main.bicep"
New-AzResourceGroupDeployment -ResourceGroupName $effectiveResourceGroup -TemplateFile $template -Verbose
```

## Returning Credentials to the User Dashboard

Write a hashtable to the output stream. The platform captures every one:

```powershell
@{ HackboxCredential = @{ name = "ResourceGroupName"; value = $ResourceGroupName; note = "Dedicated training resources" } }
```

Always return at minimum the resource group name so users can find their resources.

## lab-defaults.json: Required Shape

```json
{
"$schema": "https://raw.githubusercontent.com/microsoft/MicroHack/refs/heads/main/lab-defaults-schema.json",
"groups": [],
"deploymentType": "resourcegroup",
"labsPerSubscription": 4,
"preferredLocation": "uksouth",
"estimatedDailyCostsUsd": 15.0
}
```

- `$schema` is **required**; the platform validates against it
- `deploymentType`: `"resourcegroup"` | `"resourcegroup-with-subscriptionowner"` | `"subscription"`
- `groups`: `[]` for Azure-only; add `"GHCPUsers"` or `"M365-E5-Users"` as needed
- `preferredLocation`: one approved region for this lab; no automatic regional fallback
- `estimatedDailyCostsUsd`: planning allowance, not a verified price quote; document assumptions

## Available Platform Helper Cmdlets

| Cmdlet | Use |
|--------|-----|
| `Get-MhhStableHash` | Deterministic per-user hash for resource naming in `subscription` mode |
| `Get-MhhLabUser` | Get Entra user details for `$AllowedEntraUserIds` |
| `Invoke-MhhDeploymentWithRegionFallback` | Deploy with automatic region fallback |
| `Test-MhhDeploymentFailureRetryable` | Check if a deployment error is transient |

The fallback helpers above are part of the shared platform reference, **not
approved for this lab**: they can recycle a resource group or change regions.
Use the reviewed incremental deployment hook and obtain separate approval for
any destructive cleanup or cross-region move.
Loading
Loading