◆ Phase 1

Core Tooling — State Tracking & Brief Agent

Set up Microsoft Fabric, build the Brief Intelligence Agent in Copilot Studio, wire the Logic Apps Event Router, and connect Jira and Teams notifications. No GPT-4o authoring yet — Phase 1 proves the infrastructure before adding AI complexity.

Duration2 – 3 months
Azure cost / month~$1,400 – $5,800
Gate to Phase 25 exit criteria

Sprint Plan (6 × 2-week sprints)

Each sprint delivers a shippable increment. Infrastructure-first: Fabric and state machine before any user-facing agent.

Sprint 1–2
Weeks 1–4
Fabric Infrastructure Setup
  • Provision Microsoft Fabric capacity (F8 for dev, F32 for staging)
  • Create three Fabric workspaces: Dev, Staging, Prod
  • Define OneLake folder structure: Bronze / Silver / Gold layers with naming convention
  • Set up Fabric Eventstream: create CLProcess-events stream with schema definition
  • Configure Entra ID groups for Fabric RBAC (Admin, Contributor, Viewer per workspace)
  • Seed OneLake Gold with Phase 0 modular content inventory and claims register export
  • Write infrastructure-as-code (Bicep templates) for all Azure resources
Fabric Admin Entra ID OneLake setup
Sprint 3–4
Weeks 5–8
Brief Agent + Event Router
  • Build Brief Intelligence Agent in Copilot Studio — Teams channel deployment
  • Agent collects: objective, product, indication, channel, market, deadline, reference files
  • Agent validates completeness, posts structured brief JSON to Fabric lakehouse via Power Automate
  • Build Logic Apps Event Router: subscribe to Fabric Eventstream, define routing rules per state
  • Wire Jira integration: create task on state 1 (Brief Submitted), update on each subsequent state
  • Teams Adaptive Card notifications on each state transition (assigned reviewer + due date)
  • Test full loop: submit brief via agent → state 1 event → Jira task → Teams notification
Copilot Studio Logic Apps Jira API
Sprint 5–6
Weeks 9–12
Power BI Dashboard + UAT
  • Build Fabric semantic model on OneLake Silver layer (state transition events)
  • Create Power BI cycle time dashboard: avg days per state, active items by state, SLA breach alerts
  • User Acceptance Testing with 3 real content items: brief submission → Brand Review state
  • Document all bugs and fix within sprint. No Phase 2 start until 0 P1 bugs remain.
  • Train content ops team on brief agent, Jira workflow, and Teams notifications (1-hour session)
  • Handover runbook for Fabric Admins: capacity scaling, workspace management, Eventstream monitoring
Power BI UAT Training

What Gets Built

Microsoft Fabric + OneLake
Data platform backbone — Bronze/Silver/Gold medallion architecture
Infrastructure
OneLake Folder Structure
# OneLake workspace layout content-lifecycle-process/ ├── bronze/ │ ├── briefs/ # raw brief JSON from Copilot Studio │ ├── state-events/ # raw Eventstream payloads │ └── external-sync/ # Veeva, Jira, SAP raw dumps (Phase 2) ├── silver/ │ ├── state-transitions/ # cleaned events with duration calc │ ├── brief-enriched/ # briefs with AI enrichment (Phase 2) │ └── audit-log/ # Purview audit events (Phase 2) └── gold/ ├── content-items/ # approved master records ├── claims-register/ # seeded from Phase 0 audit └── modular-library/ # approved reusable blocks
Eventstream Schema (state-events)
{ "eventId": "uuid", "contentItemId": "string", "fromState": "string | null", // null on creation "toState": "string", "actorId": "string", // Entra ID object ID "actorRole": "string", "timestamp": "ISO 8601", "metadata": "object" // state-specific payload }
  • Delta Lake format for all OneLake tables — time-travel queries for audit
  • Fabric Data Pipeline runs nightly: Bronze → Silver transformation with deduplication
  • Silver → Gold promoted only on Approved Master state event
Brief Intake — Dual Path
Two entry points, one canonical JSON schema, one Eventstream event
Copilot Studio Jira Webhook

Both paths produce an identical BriefPayload JSON written to OneLake Bronze and fire the same content_lifecycle.state_changed{toState:"brief_submitted"} Eventstream event. Downstream systems (Event Router, Logic Apps, Power BI) are unaware of which path was used.

Canonical BriefPayload Schema
// OneLake Bronze: briefs/{contentItemId}.json { "contentItemId": "clp-2026-04-001", // generated on intake "intakeSource": "teams_agent" | "jira", "submittedBy": "entra_object_id", "submittedAt": "ISO 8601", "jiraIssueKey": "CLP-42 | null", // populated from Jira path "campaignName": "string", "objective": "string", // max 300 chars "product": "string", // validated against OneLake product list "indication": "string", "channelScope": ["web","email","field","social","print"], "marketScope": ["FR","DE","ES","IT","JP"], "requestedLiveDate": "YYYY-MM-DD", "contentType": "hcp-detail-aid | email | press-release | clm | social", "isDerivative": false, "parentItemId": "clp-2026-01-007 | null", // if derivative "referenceUrls": ["string"], "attachmentIds": ["sharepoint_item_id"] }
Path A Teams Agent (Copilot Studio) — best for brand managers, marketers, ad-hoc requests
Conversation Flow (7 steps)
  • Trigger: @ContentBrief mention in any Teams channel, or Personal App tab
  • Step 1 — Campaign name + objective: free-text. Agent paraphrases back for confirmation.
  • Step 2 — Content type: quick-reply buttons (HCP Detail Aid / Email / Press Release / CLM / Social)
  • Step 3 — Product / indication: adaptive card dropdown populated from OneLake Gold product table (refreshed nightly from SAP)
  • Step 4 — Channel scope: multi-select checkboxes (Web, Email, Field Sales, Social, Print)
  • Step 5 — Market scope: multi-select from configured market list. Agent shows estimated localisation SLA based on market count.
  • Step 6 — Requested live date: date picker. Enforces minimum T+24 working days. Shows warning if date conflicts with known market freeze periods.
  • Step 7 — Reference materials: optional file upload (→ SharePoint via Graph API) or URL. Agent checks URL is reachable.
  • Duplicate check: agent calls OneLake embedding search. If similarity >80% to existing item — shows card "Similar content exists: [title]. Create derivative instead?" with two buttons.
  • Confirmation: full brief summary card. Submitter clicks "Submit Brief" → Power Automate writes JSON to OneLake Bronze → Eventstream event fired → agent replies with ContentItemId and Jira Epic link.
Path B Jira Issue (Content Brief issue type) — best for PMs, sprint-planned content, derivative requests
Jira Project Setup — Issue Type "Content Brief"
  • Project: CLPx (Content Lifecycle Process). Type: Business project or Software project — either works.
  • Issue type "Content Brief" — custom issue type, separate from Story/Task/Bug. Icon: document. Available only in this project.
  • Required fields (validation enforced by webhook handler):
    • Summary → campaignName
    • Description → objective (min 30 chars)
    • Custom field "Product" (single-select, options synced from OneLake nightly via Jira API)
    • Custom field "Indication" (single-select)
    • Custom field "Content Type" (single-select: HCP Detail Aid / Email / Press Release / CLM / Social)
    • Custom field "Channel Scope" (multi-select checkboxes)
    • Custom field "Market Scope" (multi-select, all configured markets)
    • Custom field "Requested Live Date" (date picker)
  • Optional fields: "Parent Content Item" (text — enter existing ContentItemId to create derivative), "Reference URLs" (URL field, multi-value), Attachments (Jira native)
  • Jira screen scheme: separate Create / Edit / View screens for Content Brief — only relevant fields shown. No sprint, story points, or dev-focused fields visible to content requesters.
Jira Webhook → Azure Function Flow
# Jira webhook configuration (Admin → System → Webhooks) Name: Content Brief Intake URL: https://func-clp-prod.azurewebsites.net/api/jira-brief-intake Secret: stored in Azure Key Vault (kv-clp-prod/jira-webhook-secret) Events: issue_created (filter: project = CLPx AND issuetype = "Content Brief") issue_updated (filter: project = CLPx AND issuetype = "Content Brief" AND status changed to "Ready for Submission")
# Azure Function: jira_brief_intake/handler.py (abbreviated) def handle_jira_webhook(req): payload = req.get_json() issue = payload["issue"] fields = issue["fields"] # 1. Validate required fields errors = validate_required(fields, required=[ "summary", "description", "customfield_product", "customfield_indication", "customfield_content_type", "customfield_channel_scope", "customfield_market_scope", "customfield_live_date" ]) if errors: # post Jira comment listing missing fields, do NOT proceed jira_api.add_comment(issue["key"], build_error_comment(errors)) return 400 # 2. Normalise to BriefPayload schema brief = BriefPayload( contentItemId = generate_id(), # clp-YYYY-MM-NNN intakeSource = "jira", jiraIssueKey = issue["key"], # e.g. "CLP-42" submittedBy = fields["reporter"]["accountId"], campaignName = fields["summary"], objective = fields["description"], product = fields["customfield_product"]["value"], channelScope = [v["value"] for v in fields["customfield_channel_scope"]], marketScope = [v["value"] for v in fields["customfield_market_scope"]], isDerivative = bool(fields.get("customfield_parent_item_id")), # ... other fields ) # 3. Write to OneLake Bronze + fire Eventstream event write_onelake_bronze(brief) publish_eventstream("content_lifecycle.state_changed", brief.contentItemId, toState="brief_submitted") # 4. Write back to Jira: set ContentItemId, transition to "In Lifecycle" jira_api.update_field(issue["key"], "customfield_content_item_id", brief.contentItemId) jira_api.transition(issue["key"], transition_name="Start Lifecycle") jira_api.add_comment(issue["key"], f"✅ Brief accepted. Content item: {brief.contentItemId}") return 200
Jira Workflow for Content Brief Issue Type
  • Draft → requester fills fields, can save and return. Not yet submitted to lifecycle.
  • Ready for Submission → requester clicks "Submit". Webhook fires. Azure Function validates and writes to OneLake.
  • In Lifecycle → ContentItemId assigned. Issue becomes a read-only audit record — all state transitions now driven by the lifecycle system, not Jira-native transitions.
  • Completed / Archived → set by Logic Apps Event Router on state 8 (Live) or archive event.
  • Jira automation rule: if issue stays in "Draft" for >5 days → remind reporter via Jira notification.
Why Jira Path for Derivatives Is Especially Useful
  • PM creates a "Content Brief" Jira issue linked to an existing sprint Epic via "relates to"
  • Fills "Parent Content Item" field with ContentItemId of the approved master (e.g. clp-2026-01-007)
  • Azure Function detects isDerivative=true → pre-fills brief with parent content metadata from OneLake Gold
  • Derivative skips authoring (state 2) if content type is "localisation only" — jumps directly to state 7 (Localisation)
  • All Jira sprint planning, story point estimation, and roadmap tracking stays in Jira — lifecycle system only picks up the brief data it needs
Shared: Power Automate Flow (Teams path backend)
  • Trigger: HTTP request from Copilot Studio on brief confirmation
  • Action 1: POST brief JSON to OneLake Bronze via Fabric REST API (same endpoint as Jira Azure Function)
  • Action 2: Publish state-1 Eventstream event with intakeSource: "teams_agent"
  • Action 3: Return ContentItemId + Jira Epic deep-link to Copilot Studio for confirmation card display
Event Router (Azure Logic Apps Standard)
Single fan-out hub — Eventstream in, all downstream systems out
Logic Apps
  • Trigger: Eventstream event consumer (Fabric Eventstream → Event Hub → Logic Apps)
  • Switch on toState field: each state has its own branch
  • State 1 (Brief Submitted): create Jira ticket, post Teams card to content-ops channel, assign writer
  • State 2 (In Authoring): update Jira status, notify assigned writer with brief link
  • State 3 (Claims Check): trigger Claims Validation Azure Function (Phase 2); in Phase 1 — skip, auto-advance
  • State 4 (Brand Review): create Jira review task for Brand Owner, Teams notification with document link
  • State 5 (MLR Review): create three parallel Jira tasks (Medical/Legal/Regulatory); Teams notification; Phase 2 adds Veeva sync
  • State 6 (Approved Master): update Jira epic to Done, notify Content Owner, trigger Gold-layer write in Fabric pipeline
  • State 7 (Localisation): create Jira tasks per market, Teams notification to local market managers
  • State 8 (Live): close all Jira tasks, Teams celebration card, trigger Power BI refresh
  • SLA watchdog: scheduled Logic App runs every 4 hours, checks Silver layer for items exceeding state SLA, fires Teams escalation notification
Jira Project Configuration
Content lifecycle project — one epic per content item, tasks per state
Jira
  • Project type: Scrum. Board: Content Lifecycle Operations.
  • Epic = content item. Custom field: ContentItemId (mapped to OneLake ID)
  • Issue type hierarchy: Epic → Story (per state) → Sub-task (per reviewer in parallel states)
  • Custom workflow: mirrors 8 lifecycle states. No Jira-native transitions — all state changes driven by Logic Apps.
  • Automation rule: when all sub-tasks in state 5 (MLR) are Done → auto-transition Epic story to Approved Master
  • Label taxonomy: market, indication, channel, content-type
  • SLA: Jira Service Management SLAs configured per state (mirroring lifecycle SLAs)
Power BI Cycle Time Dashboard
Built on Fabric semantic model — OneLake Silver layer
Power BI
  • Semantic model: DirectLake mode (reads Silver layer without import) — near-real-time refresh
  • Page 1 — Active Pipeline: all items by current state, days in current state, SLA RAG status
  • Page 2 — Cycle Time Analysis: avg total days, avg per state, P50/P90 distribution, trend over time
  • Page 3 — Volume & Throughput: items submitted per week, items approved per week, revision cycle count
  • Row-level security: Content Ops sees all; Local Market managers see only their market's items
  • Alerts: Power BI Data Alerts on "Items breaching SLA" measure — Teams notification to Content Ops Lead

Service Pricing & Recommended Tiers

🗄️Microsoft Fabric Core Platform
SKUCompute UnitsPrice / monthUse Case
F22 CU$263Proof-of-concept only — limited concurrency
F44 CU$526Development workspace
F6464 CU$8,415Production (Phase 2–3)
🤖Microsoft Copilot Studio Brief Agent
PlanIncludesPriceRecommendation
Copilot Studio standalone25,000 messages/month per tenant$200 / tenant / monthOnly if org does not have M365 E3/E5
Pay-per-use overagePer message beyond included quota$0.01 / messageMonitor usage; ~10,000 messages/month expected in Phase 1
Azure Logic Apps Event Router
PlanBillingEstimated Phase 1 costNotes
Consumption$0.000025 / action + $0.08 / 1K connector calls~$20 – $80 / monthGood for low volume. Cold start latency.
📋Jira Software Cloud Task Tracking
PlanPriceKey featuresRecommendation
Free$0 (up to 10 users)Basic boards, backlogToo limited — no SLAs, no automation rules
Premium$15.25 / user / monthAdvanced roadmaps, sandbox, unlimited storageConsider for Phase 2 when volume increases
📊Power BI Analytics
LicensePriceIncluded in Fabric?Notes
Power BI Pro$10 / user / monthNo (separate)Required for sharing reports with other users. Report creators and consumers both need Pro.

Roles & Permissions

Principle of least privilege. Each role has the minimum permissions required for its function. All roles managed via Entra ID security groups — no direct user assignments.

RoleSystemPermission LevelWho holds it
Fabric Administrator Microsoft Fabric tenant Full capacity management, workspace creation, user management 1–2 people: IT Lead + backup. Azure AD role: Fabric Administrator (tenant-level).
Fabric Workspace Admin Specific workspace (Dev/Staging/Prod) Manage workspace members, settings, delete items Tech Lead per environment. Separate people for Dev vs Prod.
Fabric Contributor Specific workspace Create/edit lakehouse tables, pipelines, Eventstream, semantic models All engineers working in that workspace
Fabric Viewer Specific workspace Read reports, view dashboards. Cannot edit or create items. Business stakeholders, Content Ops Lead, CMO
OneLake Data Owner Specific OneLake path (Gold layer) Read/write Gold layer tables. Gold = approved content only. Data Engineer, Fabric Pipeline service principal
Copilot Studio Maker Microsoft Copilot Studio environment Create and edit agents, publish to Teams Developer who builds the Brief Agent. Minimum: M365 E3 + Power Platform Maker license.
Logic Apps Contributor Azure Resource Group Edit Logic App workflows, connections, run history Integration Developer. Azure RBAC: Logic Apps Contributor on resource group.
Jira Project Admin Jira project Configure board, workflow, custom fields, automation rules IT / Delivery Lead. Only 2–3 people max.
Jira Member Jira project Create, edit, transition issues they are assigned to All content team members, reviewers
Power BI Report Creator Power BI workspace Build and publish reports to shared workspace Data Analyst / BI Developer. Requires PPU or Pro license.
Power BI Report Consumer Power BI workspace View and interact with published reports Content Ops, Brand managers, CMO. Requires PPU or Pro license.
🔑 Service Principal for Automation

Logic Apps and Power Automate flows authenticate to Fabric/OneLake via a dedicated Service Principal (app registration in Entra ID). This SP has: Fabric Contributor on the workspace, OneLake Data Owner on Bronze path only. Never use a human user account for automation — it breaks when the person leaves. SP credentials stored in Azure Key Vault, referenced by Logic Apps managed identity.

Departments & Engagement Model

DepartmentRole in Phase 1Touchpoints
IT / Digital (Infrastructure) Provision Azure subscription, Fabric capacity, Entra ID groups. Own infrastructure decisions. Sprint 1 kickoff, weekly sync, infrastructure sign-off at sprint 2 end
Content Operations Primary users of Brief Agent and Jira workflow. Participate in UAT in sprint 5–6. Provide feedback on agent UX. Sprint 3 demo, UAT in sprint 5–6, training session at sprint 6
Brand & Marketing Validate brief form fields — confirm the agent asks for the right information. Review Teams Adaptive Cards design. Sprint 3 walkthrough, UAT sign-off
Medical Affairs / Legal Review Jira task structure for MLR state (state 5). Confirm parallel task assignment logic is correct. Sprint 4 review, UAT in sprint 5–6
Data Analytics / BI Co-build Power BI semantic model. Define KPI metrics. Own dashboard post-handover. Sprint 5 co-build session, dashboard review at sprint 6

Monthly Cost Estimate

Microsoft Fabric F8 (Dev) $1,052 / month
Microsoft Fabric F32 (Staging — optional, Phase 1 end) $4,208 / month
Azure Logic Apps Standard WS1 $190 / month
Azure Event Hub (Eventstream backend) ~$25 / month
Copilot Studio (if on M365 E3/E5) $0 (included)
Jira Standard (~20 users) ~$155 / month
Power BI PPU (included with Fabric F-SKU) $0 (included)
Total (Dev only, F8) ~$1,420 / month
Total (Dev + Staging, F8 + F32) ~$5,630 / month
💡 Cost Optimisation

Fabric capacity can be paused outside business hours via the Fabric Admin Portal — reduces Dev environment cost by ~65%. Set a daily schedule: pause at 19:00, resume at 08:00. F8 dev cost drops to ~$370/month with overnight pausing. Staging environment may only need to run during sprint test periods.

Exit Criteria — Gate to Phase 2

✓ Fabric Eventstream Operational

All 8 state transition events flow correctly from Bronze to Silver. Schema validated, no dropped events over 1-week observation period.

✓ Brief Agent Live in Teams

At least 10 real briefs submitted via the agent by content team (not engineers). Agent creates OneLake record and fires Eventstream event on each submission.

✓ Event Router 100% State Coverage

Logic Apps routes all 8 state transitions correctly. Jira task created on state 1, all Jira updates accurate. No manual workarounds required.

✓ Power BI Dashboard in Use

Content Ops Lead reviews the dashboard weekly. SLA breach alert has fired at least once and escalation notification was received by correct person.

✓ UAT Completed — 0 P1 Bugs

3 real content items walked through states 1–6 using the new system. No Priority 1 bugs (data loss, incorrect routing, broken audit trail).