Dec. 20, 2025
SharePoint Is Broken: The AI Governance Fix
Is SharePoint really broken in the age of artificial intelligence? Or is the real problem missing AI governance and data strategy? In this episode, I explain why traditional SharePoint architectures fail in modern AI-driven environments—and how a structured AI governance framework can fix data chaos, security risks, and compliance issues before they destroy trust in your systems. You’ll learn:
- Why SharePoint breaks under AI workloads
- How poor data governance blocks successful AI projects
- What AI governance really means in practice
- How organizations can regain control over:
- Data quality
- Security
- Compliance
- Access management
- And how to prepare SharePoint for machine learning, Copilot, and enterprise AI
- AI-powered document search in SharePoint
- Microsoft Copilot readiness
- Synthetic data vs. production data
- Secure data pipelines for machine learning
- Enterprise AI compliance strategies
- Data scientists
- IT architects
- Microsoft 365 & SharePoint admins
- AI engineers
- Security & compliance professionals
- And anyone building data-driven systems
Become a supporter of this podcast: https://www.spreaker.com/podcast/m365-show-podcast--6704921/support.
Follow us on:
Substack
Transcript
1
00:00:00,000 --> 00:00:07,760
At 0347 UTC, I detected a pattern, concurrent flow failures, permission edits without tickets,
2
00:00:07,760 --> 00:00:12,160
and three new SharePoint lists named "Test" created within 4 minutes.
3
00:00:12,160 --> 00:00:15,360
Not an outage, entropy, intervention, authorized.
4
00:00:15,360 --> 00:00:18,800
I will show you the exact controls to restore alignment.
5
00:00:18,800 --> 00:00:24,160
Disciplined SharePoint schemas, predictable Power Apps behavior, resilient flows,
6
00:00:24,160 --> 00:00:28,840
and AI that enforces boundaries instead of hallucinating past them.
7
00:00:28,840 --> 00:00:33,240
You will leave with a governance checklist that prevents this failure from repeating.
8
00:00:33,240 --> 00:00:38,440
I am not here to scold. I am here to stop the slow leak before it becomes a flood.
9
00:00:38,440 --> 00:00:41,400
Begin with the substrate SharePoint.
10
00:00:41,400 --> 00:00:45,800
Pillar 1 SharePoint, Float Substrate and Force Discipline.
11
00:00:45,800 --> 00:00:52,520
SharePoint is fine until you treat it like a database and a file share and a workflow engine on the same Tuesday.
12
00:00:52,520 --> 00:00:58,200
It's a collaboration platform with lists that behave like lightweight tables and document libraries
13
00:00:58,200 --> 00:01:04,120
that behave like content stores, that dual nature is why it's powerful and why it's fragile.
14
00:01:04,120 --> 00:01:07,800
If you don't draw the line, makers will. They will draw it with a highlighter
15
00:01:07,800 --> 00:01:10,760
and a random choice column named "Status 2".
16
00:01:10,760 --> 00:01:14,600
The thing most people miss is this. SharePoint isn't the villain.
17
00:01:14,600 --> 00:01:20,680
In consistent design is, lists scale exceptionally for thousands of items
18
00:01:20,680 --> 00:01:27,880
when queries are delegable and indexed, but they feel like wet cardboard when you bolt on 347 columns,
19
00:01:27,880 --> 00:01:33,320
5 look-up chains and a gallery trying to filter across non-indexed text.
20
00:01:33,320 --> 00:01:37,480
Do you think you need more horsepower? You really need fewer anti-patterns.
21
00:01:37,480 --> 00:01:40,760
So here's the Enforce Discipline. First, Schema.
22
00:01:40,760 --> 00:01:44,760
Name the list for the business noun, not the project nickname.
23
00:01:44,760 --> 00:01:47,960
Incidents, not Jen's trial tracker.
24
00:01:47,960 --> 00:01:52,760
Set column names that never include spaces, punctuation or future regret.
25
00:01:52,760 --> 00:01:58,200
You can relabel for humans in power apps. You can't renegotiate the API later.
26
00:01:58,200 --> 00:02:01,880
Use single line of text number date and yes, no for most fields.
27
00:02:01,880 --> 00:02:05,240
Use choice sparingly when you control the vocabulary.
28
00:02:05,240 --> 00:02:07,960
Use look-up when you actually need a relationship,
29
00:02:07,960 --> 00:02:10,920
not when you're too tired to maintain a choice list.
30
00:02:10,920 --> 00:02:16,280
Second, relationships. SharePoint look-ups are fine for one hop, too if you're lucky.
31
00:02:16,280 --> 00:02:19,480
After that, galleries cry in delegation breaks.
32
00:02:19,480 --> 00:02:23,720
If your design needs multi-hop joints or transactional integrity, stop.
33
00:02:23,720 --> 00:02:26,760
That's a dataverse or SQL conversation.
34
00:02:26,760 --> 00:02:30,120
The rule, one look-up per list view that your app relies on.
35
00:02:30,120 --> 00:02:33,000
Index the look-up column and the primary filter column.
36
00:02:33,000 --> 00:02:37,400
If it must filter by two fields, index both and use a composite view.
37
00:02:37,400 --> 00:02:40,600
Don't rely on hope, rely on indexes.
38
00:02:40,600 --> 00:02:43,240
Third, versioning and retention.
39
00:02:43,240 --> 00:02:47,480
Turn on major versioning for lists where humans edit data.
40
00:02:47,480 --> 00:02:53,480
Set a sensible cap 50 or 100, so you have a rollback window without exploding storage.
41
00:02:53,480 --> 00:02:59,160
Require checkout for document libraries where edits are frequent and sensitive.
42
00:02:59,160 --> 00:03:04,360
And set content types on the library if you need different document schemas.
43
00:03:04,360 --> 00:03:09,000
This is where you stop final v7 final before it reproduces.
44
00:03:09,000 --> 00:03:10,440
Fourth, permissions.
45
00:03:10,440 --> 00:03:13,000
Break inheritance at the site, not at the item.
46
00:03:13,000 --> 00:03:14,840
Item level permissions are a treadmill.
47
00:03:14,840 --> 00:03:19,160
You'll trip if you must protect rows, design separate lists with different scopes
48
00:03:19,160 --> 00:03:22,600
and aggregate via power apps with the user-taggate,
49
00:03:22,600 --> 00:03:27,160
or move to a platform that does row-level security without voodoo.
50
00:03:27,160 --> 00:03:30,280
Owners, members, visitors use them cleanly.
51
00:03:30,280 --> 00:03:33,800
Stop granting direct access to just one person.
52
00:03:33,800 --> 00:03:35,560
Groups exist for a reason.
53
00:03:35,560 --> 00:03:37,720
Fifth, views and thresholds.
54
00:03:37,720 --> 00:03:40,920
The 5,000 item list view threshold isn't a myth.
55
00:03:40,920 --> 00:03:42,440
It's the guardrail.
56
00:03:42,440 --> 00:03:48,440
You can store way more, but you must slice the data with indexed filters in default views.
57
00:03:48,440 --> 00:03:53,240
Create a safe filter view that every app uses as its base.
58
00:03:53,240 --> 00:03:57,320
Filter by status or modify GE today and 30 indexed.
59
00:03:57,320 --> 00:03:58,760
Teach makers to respect it.
60
00:03:58,760 --> 00:04:03,320
If they need full history, they can run a scheduled extract to a data lake,
61
00:04:03,320 --> 00:04:05,240
not live query the universe.
62
00:04:05,240 --> 00:04:07,640
Sixth, files versus attachments.
63
00:04:07,640 --> 00:04:09,640
Attachments are a convenience text.
64
00:04:09,640 --> 00:04:11,960
Use document libraries for real files.
65
00:04:11,960 --> 00:04:15,400
Store the list item ID as metadata on the file
66
00:04:15,400 --> 00:04:18,920
or use a folder named with the item ID if you enjoy pain.
67
00:04:18,920 --> 00:04:23,400
Libraries give you co-authoring, retention labels and previews.
68
00:04:23,400 --> 00:04:24,760
Attachments give you drama.
69
00:04:24,760 --> 00:04:27,880
Seventh, ALM reality.
70
00:04:27,880 --> 00:04:30,600
SharePoint is stubborn in ALM.
71
00:04:30,600 --> 00:04:33,800
Lists don't package cleanly across environments,
72
00:04:33,800 --> 00:04:36,840
so you standardize a provisioning script,
73
00:04:36,840 --> 00:04:40,200
JSONSite scripts, or P&P templates,
74
00:04:40,200 --> 00:04:44,360
creates sites, content types, lists, columns, views and indexes.
75
00:04:44,360 --> 00:04:45,880
The app never creates schema.
76
00:04:45,880 --> 00:04:47,640
Humans never create schema in production.
77
00:04:47,640 --> 00:04:49,240
If that sounds strict, good.
78
00:04:49,240 --> 00:04:50,920
It's cheaper than reconstruction.
79
00:04:50,920 --> 00:04:52,840
Eighth, DELEGABL logic.
80
00:04:52,840 --> 00:04:56,280
Power apps can query SharePoint efficiently
81
00:04:56,280 --> 00:04:58,680
if you write DELEGABL formulas.
82
00:04:58,680 --> 00:05:01,640
That means filter sort, search with indexed columns.
83
00:05:01,640 --> 00:05:03,400
No for all over entire lists.
84
00:05:03,400 --> 00:05:06,040
No giant with chains as pseudo queries.
85
00:05:06,040 --> 00:05:08,600
If you need fuzzy matching and composites,
86
00:05:08,600 --> 00:05:13,720
build a helper column that concatenates normalized keys at right time.
87
00:05:13,720 --> 00:05:16,920
It's ugly, but it keeps the query on the server
88
00:05:16,920 --> 00:05:20,360
instead of dragging 25,000 rows to the client.
89
00:05:20,360 --> 00:05:22,520
Ninth, data ownership.
90
00:05:22,520 --> 00:05:25,160
Every list has an accountable owner, not IT.
91
00:05:25,160 --> 00:05:28,600
Expiring ownership reviews run quarterly.
92
00:05:28,600 --> 00:05:31,560
If the owner leaves, the site's secondary owner is notified
93
00:05:31,560 --> 00:05:33,160
and the app is re-homed.
94
00:05:33,160 --> 00:05:34,600
No orphans.
95
00:05:34,600 --> 00:05:37,720
No mystery lists with business critical data
96
00:05:37,720 --> 00:05:38,840
and a dead mailbox.
97
00:05:38,840 --> 00:05:41,400
Finally, a sanity rule.
98
00:05:41,400 --> 00:05:45,240
If your list needs more than one multi-line rich text field,
99
00:05:45,240 --> 00:05:48,920
several lookups and people fields, stop and reassess.
100
00:05:48,920 --> 00:05:52,520
You're designing a relational model with a collaboration tool.
101
00:05:52,520 --> 00:05:54,680
Move the core data to dataverse.
102
00:05:54,680 --> 00:05:57,960
Keep SharePoint for files and light reference tables
103
00:05:57,960 --> 00:05:59,160
and connect them.
104
00:05:59,160 --> 00:06:00,840
Hybrid beats heroic hacks.
105
00:06:00,840 --> 00:06:04,200
Enforced discipline isn't glamorous.
106
00:06:04,200 --> 00:06:07,640
It is the difference between predictable performance
107
00:06:07,640 --> 00:06:09,400
and slow motion collapse.
108
00:06:09,400 --> 00:06:11,960
You stabilize the substrate or everything above it
109
00:06:11,960 --> 00:06:13,240
inherits the wobble.
110
00:06:13,240 --> 00:06:14,600
Now we move up the stack.
111
00:06:14,600 --> 00:06:16,440
Pillar 2.
112
00:06:16,440 --> 00:06:17,320
Power Apps.
113
00:06:17,320 --> 00:06:18,840
Deterministic canvas.
114
00:06:18,840 --> 00:06:20,120
Not a scrapbook.
115
00:06:20,120 --> 00:06:21,480
Stabilize SharePoint.
116
00:06:21,480 --> 00:06:23,160
Then make the app behave.
117
00:06:23,160 --> 00:06:25,400
A canvas app is either deterministic
118
00:06:25,400 --> 00:06:27,240
or it's chaos with a save button.
119
00:06:27,240 --> 00:06:29,960
We bias every decision toward predictability,
120
00:06:29,960 --> 00:06:32,600
repeatability, and clear failure modes.
121
00:06:32,600 --> 00:06:34,040
No improvisation.
122
00:06:34,040 --> 00:06:35,400
No ransom node UI.
123
00:06:36,440 --> 00:06:38,040
Started the connector.
124
00:06:38,040 --> 00:06:40,920
Add SharePoint as a data source
125
00:06:40,920 --> 00:06:43,880
but never let controls query lists directly.
126
00:06:43,880 --> 00:06:45,800
Centralize reads and writes.
127
00:06:45,800 --> 00:06:49,000
On app, on start, define a configuration record
128
00:06:49,000 --> 00:06:52,040
and pre-compute the queries you'll need repeatedly.
129
00:06:52,040 --> 00:06:53,880
Not everything loads at startup.
130
00:06:53,880 --> 00:06:56,520
Only seed data and user context.
131
00:06:56,520 --> 00:06:57,560
Example.
132
00:06:57,560 --> 00:06:59,240
Set var user.
133
00:06:59,240 --> 00:07:00,600
User.
134
00:07:00,600 --> 00:07:02,280
Set var today.
135
00:07:02,280 --> 00:07:03,400
Today.
136
00:07:03,400 --> 00:07:04,360
Clear collect.
137
00:07:04,360 --> 00:07:05,880
Call my filter.
138
00:07:05,880 --> 00:07:06,920
Status.
139
00:07:06,920 --> 00:07:07,880
Active.
140
00:07:07,880 --> 00:07:11,640
Then defer heavy list loads to screen level
141
00:07:11,640 --> 00:07:14,040
on visible with controlled filters.
142
00:07:14,040 --> 00:07:18,520
This prevents the first paint lag that people blame on SharePoint
143
00:07:18,520 --> 00:07:21,880
when it's really your app dragging a list view by the ankles.
144
00:07:21,880 --> 00:07:24,760
Gallery's versus forms is not a style choice.
145
00:07:24,760 --> 00:07:25,880
Gallery's display.
146
00:07:25,880 --> 00:07:27,480
Forms commit.
147
00:07:27,480 --> 00:07:31,480
Use a gallery for list browsing with a strictly
148
00:07:31,480 --> 00:07:36,280
delegable items formula. filter, incidence, status,
149
00:07:36,280 --> 00:07:39,080
eighth, active, intent modified,
150
00:07:39,080 --> 00:07:41,560
ill var, today, 30.
151
00:07:41,560 --> 00:07:44,520
Both status and modified must be indexed.
152
00:07:44,520 --> 00:07:48,680
Don't compose data inside the gallery with if chains and lookup calls.
153
00:07:48,680 --> 00:07:51,960
Pre-compute lookups into lightweight collections
154
00:07:51,960 --> 00:07:55,560
at app start if you must display friendly names.
155
00:07:55,560 --> 00:07:57,880
The goal is one delegable server query.
156
00:07:57,880 --> 00:07:59,960
Not 10 client stunts.
157
00:07:59,960 --> 00:08:03,320
For editing default to edit form with submit form
158
00:08:03,320 --> 00:08:07,000
when your schema is simple and you can live within its life cycle.
159
00:08:07,000 --> 00:08:10,920
Submit form handles validation tied to data cards,
160
00:08:10,920 --> 00:08:13,480
patches attachments behind the scenes,
161
00:08:13,480 --> 00:08:17,640
and manages optimistic concurrency the way SharePoint expects.
162
00:08:17,640 --> 00:08:20,280
But treat submit form as an atomic operation.
163
00:08:20,280 --> 00:08:22,840
Don't wrap it in five other steps and hope.
164
00:08:22,840 --> 00:08:26,040
Use on success and on failure explicitly.
165
00:08:26,040 --> 00:08:28,680
On success logs what changed and navigates.
166
00:08:29,320 --> 00:08:33,400
On failure surfaces the error with a message that means something.
167
00:08:33,400 --> 00:08:37,560
Notify save failed check required fields or concurrency.
168
00:08:37,560 --> 00:08:39,960
Notification type dot error.
169
00:08:39,960 --> 00:08:42,040
Now the hard truth.
170
00:08:42,040 --> 00:08:45,800
The thing most people miss is knowing when to step outside the form.
171
00:08:45,800 --> 00:08:47,800
If you need partial updates,
172
00:08:47,800 --> 00:08:51,800
transformations before write or cross entity coordination,
173
00:08:51,800 --> 00:08:55,080
patch is the tool patch writes exactly what you tell it
174
00:08:55,080 --> 00:08:57,320
and nothing else that's good and dangerous.
175
00:08:57,320 --> 00:09:02,040
Guard it. Use a typed template record to make patch readable and maintainable.
176
00:09:02,040 --> 00:09:06,200
Patch incidents ID var edited,
177
00:09:06,200 --> 00:09:07,400
do data,
178
00:09:07,400 --> 00:09:08,600
itag,
179
00:09:08,600 --> 00:09:10,600
var itag,
180
00:09:10,600 --> 00:09:11,880
status,
181
00:09:11,880 --> 00:09:13,480
drp status,
182
00:09:13,480 --> 00:09:18,280
selected, value priority,
183
00:09:18,280 --> 00:09:21,560
drp priority selected,
184
00:09:21,560 --> 00:09:24,840
value title,
185
00:09:24,840 --> 00:09:26,680
text, title,
186
00:09:27,640 --> 00:09:28,760
text,
187
00:09:28,760 --> 00:09:32,520
always include the itag for basic concurrency defense.
188
00:09:32,520 --> 00:09:35,160
If SharePoint returns a conflict,
189
00:09:35,160 --> 00:09:38,680
you'll get a clear error instead of a silent override,
190
00:09:38,680 --> 00:09:41,400
handle it in a retry pattern with a
191
00:09:41,400 --> 00:09:43,160
Rack query and merge prompt,
192
00:09:43,160 --> 00:09:45,080
not a brute force write.
193
00:09:45,080 --> 00:09:46,360
Never patch attachments.
194
00:09:46,360 --> 00:09:50,760
Use a document library bound by item ID.
195
00:09:50,760 --> 00:09:54,760
Store the file in the library with metadata item ID equals this item.
196
00:09:54,760 --> 00:10:02,120
ID then display via an nested gallery that gives you co-authoring previews, labels and zero ambiguity.
197
00:10:02,120 --> 00:10:07,720
The just add an attachment shortcut is why your users keep emailing copies for reference.
198
00:10:07,720 --> 00:10:10,200
Control state explicitly.
199
00:10:10,200 --> 00:10:13,720
Apps drift when every control sets global variables.
200
00:10:13,720 --> 00:10:18,280
Prefer context, update context for purse screen flags,
201
00:10:18,280 --> 00:10:24,680
and a small set of global bars for cross app concepts like var user and feature toggles.
202
00:10:25,240 --> 00:10:29,800
Build a single record for the edit buffer, set var edit defaults incidents,
203
00:10:29,800 --> 00:10:32,920
then write forms and controls to bind to var edit fields.
204
00:10:32,920 --> 00:10:35,080
When you save map var edit to patch,
205
00:10:35,080 --> 00:10:40,280
that isolates UI twitching from data integrity and makes undo trivial,
206
00:10:40,280 --> 00:10:44,600
set var edit blank or reload it from the source.
207
00:10:44,600 --> 00:10:48,280
Validation belongs in three places in order.
208
00:10:48,280 --> 00:10:51,720
First server side rules in SharePoint where possible,
209
00:10:51,720 --> 00:10:57,080
required columns max lengths unique constraints via calculated keys.
210
00:10:57,080 --> 00:11:01,400
Second data card required and valid properties aligned with those rules
211
00:11:01,400 --> 00:11:02,680
not invented on the fly.
212
00:11:02,680 --> 00:11:05,000
Third presubmit guardrails.
213
00:11:05,000 --> 00:11:13,400
If form incidents, valid notify fix validation errors, warning, return.
214
00:11:13,400 --> 00:11:19,880
The reason this works is you're reusing the engine's validation instead of reinventing it 12 times.
215
00:11:20,680 --> 00:11:23,640
Navigation patterns should be linear and idempotent.
216
00:11:23,640 --> 00:11:28,840
Users start at a filtered list, select a record, edit in a separate screen,
217
00:11:28,840 --> 00:11:33,240
commit, return to the same filter with the same scroll position.
218
00:11:33,240 --> 00:11:35,560
Don't rebuild the universe on every navigate.
219
00:11:35,560 --> 00:11:39,400
Cash the list query seed in a variable.
220
00:11:39,400 --> 00:11:43,720
When you save, refresh only the changed row with a targeted update,
221
00:11:43,720 --> 00:11:46,520
if into a local collection bound to the gallery,
222
00:11:46,520 --> 00:11:50,040
that avoids full round trips and preserves context.
223
00:11:50,040 --> 00:11:53,000
Styling is a governance problem disguised as taste.
224
00:11:53,000 --> 00:11:55,080
Define a theme record in app.
225
00:11:55,080 --> 00:11:58,760
On start, set of our theme, primary,
226
00:11:58,760 --> 00:12:02,200
test 0, 0, 4, 5, 7, 8, text,
227
00:12:02,200 --> 00:12:06,760
su11, danger, c50, f1,
228
00:12:06,760 --> 00:12:09,480
all controls reference for theme.
229
00:12:09,480 --> 00:12:10,760
Lock fonts and sizes.
230
00:12:10,760 --> 00:12:13,320
If someone demands a gradient, you decline.
231
00:12:13,320 --> 00:12:15,320
Consistency isn't pretty.
232
00:12:15,320 --> 00:12:16,680
It's maintainable.
233
00:12:16,680 --> 00:12:18,520
The app should look boring and run fast.
234
00:12:18,520 --> 00:12:19,960
Offline is not a checkbox.
235
00:12:19,960 --> 00:12:25,240
If you don't have a tested store load pattern with JSON serialization and conflict resolution,
236
00:12:25,240 --> 00:12:26,360
you don't have offline.
237
00:12:26,360 --> 00:12:28,360
Say no until you can say yes properly.
238
00:12:28,360 --> 00:12:31,160
Half offline creates full incidents.
239
00:12:31,160 --> 00:12:32,680
Finally, instrumentation.
240
00:12:32,680 --> 00:12:34,920
The app logs its own behavior.
241
00:12:34,920 --> 00:12:37,000
On start, write a session record.
242
00:12:37,000 --> 00:12:46,200
On every save, log patch with request id, user, record id, operation, duration, success, error.
243
00:12:46,200 --> 00:12:50,520
If a flow is involved, correlate with a guide passed into the trigger.
244
00:12:50,520 --> 00:12:53,960
When the O347 spike hits again, you won't guess.
245
00:12:53,960 --> 00:12:54,840
You'll see.
246
00:12:54,840 --> 00:12:57,320
Deterministic apps tell you what they did,
247
00:12:57,320 --> 00:12:58,760
not what they hoped to do.
248
00:12:58,760 --> 00:13:00,760
Pillar 3.
249
00:13:00,760 --> 00:13:02,120
Power automate.
250
00:13:02,120 --> 00:13:03,080
Timebombs.
251
00:13:03,080 --> 00:13:04,920
Defused with protocols.
252
00:13:04,920 --> 00:13:07,800
Flows fail the same way buildings burn,
253
00:13:07,800 --> 00:13:09,800
quietly at first, then all at once.
254
00:13:09,800 --> 00:13:13,320
The O347 spike wasn't mysterious.
255
00:13:13,320 --> 00:13:17,480
A SharePoint column was renamed, an approval owner was on leave,
256
00:13:17,480 --> 00:13:22,280
and a flow with 47 unguarded steps marched straight into nulls and stayed there.
257
00:13:22,280 --> 00:13:24,200
We don't fix this with hope.
258
00:13:24,200 --> 00:13:28,520
We fix it with protocols that make failure loud, contained, and reversible.
259
00:13:28,520 --> 00:13:30,200
Start with triggers.
260
00:13:30,200 --> 00:13:36,040
When an item is created or modified is not a strategy, it's a floodgate.
261
00:13:36,040 --> 00:13:37,080
Scope it.
262
00:13:37,080 --> 00:13:41,080
In the trigger, add filter queries that match your app's delegable base.
263
00:13:41,720 --> 00:13:45,480
Status EQ pending and modify GUTC now.
264
00:13:45,480 --> 00:13:46,440
Sub 1.
265
00:13:46,440 --> 00:13:48,120
Index those columns in the list.
266
00:13:48,120 --> 00:13:51,320
If you need a change detector, use a calculated hash column.
267
00:13:51,320 --> 00:13:54,680
The app updates only when a meaningful field changes.
268
00:13:54,680 --> 00:13:58,120
Your trigger wakes up for intent, not background noise.
269
00:13:58,120 --> 00:13:59,640
Next, concurrency.
270
00:13:59,640 --> 00:14:04,280
Turn on trigger concurrency control and cap degree to one for workflows
271
00:14:04,280 --> 00:14:08,280
that touch the same record, or you'll race yourself into conflicts.
272
00:14:08,280 --> 00:14:09,800
For bulk handlers,
273
00:14:09,800 --> 00:14:14,680
batch by partition keys like site or department with a degree of 5 to 10.
274
00:14:14,680 --> 00:14:18,680
Unbounded parallelism is how you turn a hiccup into a pile-up.
275
00:14:18,680 --> 00:14:21,080
Conditions aren't decorations.
276
00:14:21,080 --> 00:14:23,800
Use guard clauses early and often.
277
00:14:23,800 --> 00:14:27,800
The first branch in the flow should answer, should I even be running?
278
00:14:27,800 --> 00:14:32,520
If the item status isn't pending, terminate is succeeded with a reason.
279
00:14:32,520 --> 00:14:37,560
If required fields are blank, terminate is failed with a specific code.
280
00:14:37,560 --> 00:14:41,160
Dead end quietly is not resilience. It's a cover-up.
281
00:14:41,160 --> 00:14:44,520
Approvals look simple until someone goes on vacation.
282
00:14:44,520 --> 00:14:48,280
Use the built-in start and wait for an approval for human decisions.
283
00:14:48,280 --> 00:14:50,120
But rapid with reality.
284
00:14:50,120 --> 00:14:52,040
Set a business realistic timeout.
285
00:14:52,040 --> 00:14:53,160
72 hours.
286
00:14:53,160 --> 00:14:54,200
Not forever.
287
00:14:54,200 --> 00:14:57,000
On timeout, branch to an escalation path.
288
00:14:57,000 --> 00:14:59,640
Notify the requester.
289
00:14:59,640 --> 00:15:03,240
Notify a backup approval group and log a governance event.
290
00:15:03,240 --> 00:15:05,320
If your culture requires reassign,
291
00:15:05,320 --> 00:15:07,880
use entra-groups instead of individuals,
292
00:15:07,880 --> 00:15:10,120
so-coverage rotates without edits.
293
00:15:10,120 --> 00:15:13,400
The thing most people miss is that approvals are state machines.
294
00:15:13,400 --> 00:15:15,400
Your list item should reflect that state.
295
00:15:15,400 --> 00:15:18,600
Write a status, ex-awaiting approval,
296
00:15:18,600 --> 00:15:19,880
then approved,
297
00:15:19,880 --> 00:15:21,000
or rejected,
298
00:15:21,000 --> 00:15:22,760
and a decision by field.
299
00:15:22,760 --> 00:15:28,200
The flow reads and writes that state explicitly to survive retries and human drift.
300
00:15:28,200 --> 00:15:30,840
Data operations are where promises go to die.
301
00:15:30,840 --> 00:15:33,000
Parse Jason everywhere is shape matters.
302
00:15:33,000 --> 00:15:35,080
Stop guessing at dynamic content.
303
00:15:35,080 --> 00:15:38,920
Define a contract for each connector's response and fail fast if it changes.
304
00:15:38,920 --> 00:15:42,840
Use try catch patterns with scope actions.
305
00:15:42,840 --> 00:15:45,160
A try scope for your main logic,
306
00:15:45,160 --> 00:15:49,560
then a catch scope configured to run on failure, timeout, or skipped.
307
00:15:49,560 --> 00:15:51,400
In catch, gather context.
308
00:15:51,400 --> 00:15:53,320
Flow run ID.
309
00:15:53,320 --> 00:15:54,440
Item ID.
310
00:15:54,440 --> 00:15:55,320
ETAG.
311
00:15:55,320 --> 00:15:57,480
Correlation ID from the app.
312
00:15:57,480 --> 00:15:59,800
And send a single consolidated alert.
313
00:15:59,800 --> 00:16:02,680
The game changer nobody talks about is correlation.
314
00:16:02,680 --> 00:16:06,840
Pass a guide from the app into the flow trigger and write it into every log,
315
00:16:06,840 --> 00:16:08,840
email, subject, and team's card.
316
00:16:08,840 --> 00:16:10,840
When the spike hits,
317
00:16:10,840 --> 00:16:15,400
you follow one ID through app, flow, and SharePoint updates without guessing.
318
00:16:15,400 --> 00:16:18,040
SharePoint writes need optimism with proof.
319
00:16:18,040 --> 00:16:19,880
Before you update item,
320
00:16:19,880 --> 00:16:22,520
get the current item to retrieve the ETAG,
321
00:16:22,520 --> 00:16:25,480
write back with if match header, where available,
322
00:16:25,480 --> 00:16:30,680
or use the update item action and check for 412 precondition failed in the error.
323
00:16:30,680 --> 00:16:34,040
If someone edited the record between trigger and write,
324
00:16:34,040 --> 00:16:35,560
don't bulldoze.
325
00:16:35,560 --> 00:16:38,280
Branch to emerge path, read fresh,
326
00:16:38,280 --> 00:16:39,800
compare changed fields,
327
00:16:39,800 --> 00:16:43,560
and either reapply or ask the requester to reconcile.
328
00:16:43,560 --> 00:16:45,640
Silent overrides are how you lose trust.
329
00:16:45,640 --> 00:16:48,360
Long flows need checkpoints.
330
00:16:48,360 --> 00:16:51,080
After each critical mutation,
331
00:16:51,080 --> 00:16:54,520
persist a last processed step field to the list,
332
00:16:54,520 --> 00:16:55,960
or a shadow tracking list,
333
00:16:55,960 --> 00:16:59,000
keyed by the item ID and correlation,
334
00:16:59,000 --> 00:17:00,520
key UID.
335
00:17:00,520 --> 00:17:04,840
On rerun, the first action reads that check point and jumps to the next block
336
00:17:04,840 --> 00:17:06,840
that makes your flow id important.
337
00:17:06,840 --> 00:17:08,600
Replace, don't double charge you,
338
00:17:08,600 --> 00:17:11,000
or send two emails to the CFO.
339
00:17:11,000 --> 00:17:12,360
Files are their own trap.
340
00:17:12,360 --> 00:17:14,120
If the flow handles documents,
341
00:17:14,120 --> 00:17:17,320
use document libraries and content types,
342
00:17:17,320 --> 00:17:18,600
not list attachments.
343
00:17:18,600 --> 00:17:22,680
Use get file content using path,
344
00:17:22,680 --> 00:17:24,120
only when you must,
345
00:17:24,120 --> 00:17:26,440
prefer IDs to avoid path drift.
346
00:17:27,160 --> 00:17:29,960
When generating files write metadata first,
347
00:17:29,960 --> 00:17:31,240
then upload content,
348
00:17:31,240 --> 00:17:34,600
then update the metadata that depends on the file version.
349
00:17:34,600 --> 00:17:38,200
It's boring and keeps preview retention and labels intact.
350
00:17:38,200 --> 00:17:40,360
Error handling is not just a catch scope.
351
00:17:40,360 --> 00:17:41,640
It's classification.
352
00:17:41,640 --> 00:17:43,400
Not all failures are equal.
353
00:17:43,400 --> 00:17:44,440
Build three paths,
354
00:17:44,440 --> 00:17:46,680
retriable, permanent, and unknown.
355
00:17:46,680 --> 00:17:51,640
Retriable errors include 429 and 5xx responses,
356
00:17:51,640 --> 00:17:55,560
RAP with exponential delay max 3 attempts,
357
00:17:55,560 --> 00:18:00,360
permanent errors include 400-level validation failures,
358
00:18:00,360 --> 00:18:05,400
notify the maker with exact field names and values,
359
00:18:05,400 --> 00:18:09,720
unknown errors dump the raw body and headers to a secure log store
360
00:18:09,720 --> 00:18:10,920
with the correlation,
361
00:18:10,920 --> 00:18:12,600
GUID and environment.
362
00:18:12,600 --> 00:18:14,760
Do not paste secrets into teams.
363
00:18:14,760 --> 00:18:16,520
Mask payloads by default.
364
00:18:16,520 --> 00:18:18,840
Notifications must be quiet and useful,
365
00:18:18,840 --> 00:18:21,640
one message per incident, not per action.
366
00:18:21,640 --> 00:18:23,560
Use adaptive cards with the correlation
367
00:18:23,560 --> 00:18:26,600
GUID, the item link, the failed step, and the next action.
368
00:18:26,600 --> 00:18:30,360
Send to a monitor channel, not a person.
369
00:18:30,360 --> 00:18:33,880
The channel has an incident header that flips from green to amber
370
00:18:33,880 --> 00:18:36,280
when any unknown error posts,
371
00:18:36,280 --> 00:18:39,560
back to green when a resolver clicks acknowledge,
372
00:18:39,560 --> 00:18:42,520
and the system confirms the next run succeeded.
373
00:18:42,520 --> 00:18:44,680
Speaking of next runs,
374
00:18:44,680 --> 00:18:46,520
build a manual replay,
375
00:18:46,520 --> 00:18:51,000
add an HTTP triggered flow or a power app admin screen
376
00:18:51,000 --> 00:18:55,160
that takes the correlation GUID, looks up the item,
377
00:18:55,160 --> 00:18:57,560
and restarts from the last safe checkpoint.
378
00:18:57,560 --> 00:18:59,480
Log who replayed and why,
379
00:18:59,480 --> 00:19:01,880
humans will intervene, make it auditable.
380
00:19:01,880 --> 00:19:04,600
Finally document the contract.
381
00:19:04,600 --> 00:19:07,080
In the list description, link to a runbook,
382
00:19:07,080 --> 00:19:09,160
trigger filters, required fields,
383
00:19:09,160 --> 00:19:11,560
approval SLAs, error classes,
384
00:19:11,560 --> 00:19:14,200
checkpoint fields, and replay steps.
385
00:19:14,200 --> 00:19:15,480
Make us come and go.
386
00:19:15,480 --> 00:19:17,160
Protocols persist.
387
00:19:17,160 --> 00:19:19,160
When someone renames a column at midnight,
388
00:19:19,160 --> 00:19:20,680
the flow doesn't collapse.
389
00:19:20,680 --> 00:19:22,920
It complains loudly with a map.
390
00:19:22,920 --> 00:19:24,760
That's the difference between a time bomb
391
00:19:24,760 --> 00:19:26,280
and a controlled burn.
392
00:19:26,280 --> 00:19:27,400
Pillar 4.
393
00:19:27,400 --> 00:19:28,680
AI builder.
394
00:19:28,680 --> 00:19:31,400
Documents with a sober human in the loop.
395
00:19:31,400 --> 00:19:33,560
The spike didn't start with code.
396
00:19:33,560 --> 00:19:35,000
It started with a PDF.
397
00:19:35,000 --> 00:19:38,520
Invoices arrived, someone retiped line items by hand,
398
00:19:38,520 --> 00:19:41,880
and a flow tried to guess which totals mattered.
399
00:19:41,880 --> 00:19:44,360
Guessing is how you get midnight incidents.
400
00:19:44,360 --> 00:19:46,680
So we extract data like adults
401
00:19:46,680 --> 00:19:49,320
with a trained model, a stable schema,
402
00:19:49,320 --> 00:19:52,040
and a checkpoint where a human confirms.
403
00:19:52,040 --> 00:19:54,360
Here's the disciplined pattern.
404
00:19:54,360 --> 00:19:57,320
Use AI builder's document processing model
405
00:19:57,320 --> 00:20:00,360
for structured forms you see repeatedly.
406
00:20:00,360 --> 00:20:03,560
Invoice intake form inspection report.
407
00:20:03,560 --> 00:20:06,840
Train on 5 to 10 clean exemplars that match the layout.
408
00:20:06,840 --> 00:20:10,360
Define the exact fields your system cares about.
409
00:20:10,360 --> 00:20:14,200
Vendor name, invoice number, invoice date,
410
00:20:14,200 --> 00:20:17,560
subtotal, tax, total, purchase order,
411
00:20:17,560 --> 00:20:20,920
and a calculated hash that your downstream logic uses
412
00:20:20,920 --> 00:20:22,680
to detect duplicates.
413
00:20:22,680 --> 00:20:25,000
Keep the field names boring and permanent,
414
00:20:25,000 --> 00:20:26,600
boring prevents drift.
415
00:20:26,600 --> 00:20:29,400
In Power Automate, trigger on a document arriving
416
00:20:29,400 --> 00:20:32,280
in a dedicated library with a content type like invoice.
417
00:20:32,280 --> 00:20:34,760
Pass the file content into the predict action.
418
00:20:34,760 --> 00:20:37,720
Immediately parse every field with parse jason
419
00:20:37,720 --> 00:20:39,960
using a contract you control.
420
00:20:39,960 --> 00:20:42,840
No dynamic content roulette.
421
00:20:42,840 --> 00:20:44,200
Compute your own total,
422
00:20:44,200 --> 00:20:48,040
equal, subtotal, plus tax, and compare to the models total.
423
00:20:48,040 --> 00:20:51,640
If mismatch branch to human review equals required,
424
00:20:51,640 --> 00:20:53,640
human in the loop is not an apology.
425
00:20:53,640 --> 00:20:56,360
It's a gate, create an approval,
426
00:20:56,360 --> 00:20:59,640
or a custom review screen in a lightweight admin app
427
00:20:59,640 --> 00:21:01,960
that binds to a review queue list.
428
00:21:01,960 --> 00:21:04,360
Store the extracted fields, a confidence score,
429
00:21:04,360 --> 00:21:06,440
a file link, and a correlation guide
430
00:21:06,440 --> 00:21:09,960
he handed down from the app or generated ad ingestion.
431
00:21:09,960 --> 00:21:13,240
The reviewer edits fields if needed and clicks confirm.
432
00:21:13,240 --> 00:21:16,600
Only then does the flow right to the system of record
433
00:21:16,600 --> 00:21:20,280
and move the file to a processed folder with a retention label.
434
00:21:20,280 --> 00:21:22,920
The thing most people miss is grounding the model
435
00:21:22,920 --> 00:21:25,160
with deterministic checks.
436
00:21:25,160 --> 00:21:28,200
Validate vendor name against a supplier table.
437
00:21:28,200 --> 00:21:31,160
Validate invoice number uniqueness per vendor.
438
00:21:31,160 --> 00:21:33,960
Validate invoice date within a sane range.
439
00:21:33,960 --> 00:21:36,840
If any validation fails, you don't hope it's fine.
440
00:21:36,840 --> 00:21:40,280
You route to review and tag the incident
441
00:21:40,280 --> 00:21:42,440
with a reason code for telemetry.
442
00:21:42,440 --> 00:21:47,400
Low confidence, math mismatch, unknown vendor duplicate.
443
00:21:47,400 --> 00:21:50,200
That turns random review into measurable work.
444
00:21:50,200 --> 00:21:52,680
Storage is clear, do not save business files
445
00:21:52,680 --> 00:21:54,200
as list attachments.
446
00:21:54,200 --> 00:21:57,240
The document lives in a library with content types,
447
00:21:57,240 --> 00:21:58,840
labels, and versioning.
448
00:21:58,840 --> 00:22:02,280
The extracted fields live in a list or dataverse table,
449
00:22:02,280 --> 00:22:05,800
keyed by document ID and correlation guide.
450
00:22:05,800 --> 00:22:07,560
If finance wants exports,
451
00:22:07,560 --> 00:22:09,960
schedule an extract to a data lake.
452
00:22:09,960 --> 00:22:13,240
Do not let them build wild queries against live libraries.
453
00:22:13,240 --> 00:22:15,560
Retraining is periodic, not impulsive.
454
00:22:15,560 --> 00:22:19,080
When you see repeat low confidence for a vendor's new template,
455
00:22:19,080 --> 00:22:20,760
you add two fresh samples,
456
00:22:20,760 --> 00:22:22,840
retrain and version the model.
457
00:22:22,840 --> 00:22:25,960
You only switch the production flow to the new model ID
458
00:22:25,960 --> 00:22:28,840
after a test run with held out documents
459
00:22:28,840 --> 00:22:30,520
passes your validation checks.
460
00:22:30,520 --> 00:22:32,600
Models get change control like code.
461
00:22:32,600 --> 00:22:36,440
Finally, every step logs with the correlation guide.
462
00:22:36,440 --> 00:22:39,240
File captured, prediction complete.
463
00:22:39,240 --> 00:22:43,560
Validation pass, fail, human decision, write committed.
464
00:22:43,560 --> 00:22:49,000
If the O347 pattern returns, you trace it by G-wide, not by rumor.
465
00:22:49,000 --> 00:22:52,680
AI helps when it's fenced, measured, and humble.
466
00:22:52,680 --> 00:22:54,280
The fence is the human checkpoint.
467
00:22:54,280 --> 00:22:58,120
The measurement is validation and telemetry.
468
00:22:58,120 --> 00:23:01,880
The humility is knowing when to ask.
469
00:23:01,880 --> 00:23:05,480
Ah, pillar five, Copilot Studio, chat with boundaries,
470
00:23:05,480 --> 00:23:06,680
not a megaphone.
471
00:23:06,680 --> 00:23:09,480
The other spike came from words, not numbers.
472
00:23:09,480 --> 00:23:12,920
A chat agent answered a sensitive question, a little too well.
473
00:23:12,920 --> 00:23:15,800
That's not intelligence, that's a megaphone with no volume knob.
474
00:23:15,800 --> 00:23:18,120
We build agents that know their lane,
475
00:23:18,120 --> 00:23:19,560
cite their sources,
476
00:23:19,560 --> 00:23:22,440
and go silent when the question crosses a line.
477
00:23:22,440 --> 00:23:24,040
Start with purpose.
478
00:23:24,040 --> 00:23:25,560
The agent does one thing.
479
00:23:25,560 --> 00:23:29,240
Resolve how to and policy questions for a bounded domain
480
00:23:29,240 --> 00:23:31,640
like expense, policy, and process.
481
00:23:31,640 --> 00:23:34,920
Knowledge sources are white listed SharePoint pages
482
00:23:34,920 --> 00:23:37,640
with current policies and FAQ list.
483
00:23:37,640 --> 00:23:39,400
No broad web search.
484
00:23:39,400 --> 00:23:40,840
You set that to off.
485
00:23:40,840 --> 00:23:43,560
The agent reads from curated content only.
486
00:23:43,560 --> 00:23:47,320
Every response includes citations to the exact page or list item.
487
00:23:47,320 --> 00:23:49,080
If it can't cite, it won't say.
488
00:23:49,080 --> 00:23:50,280
Next, guardrails.
489
00:23:50,280 --> 00:23:53,480
You define instruction rules that survive clever prompts.
490
00:23:53,480 --> 00:23:55,240
It answers operational questions.
491
00:23:55,240 --> 00:23:58,600
It does not generate or summarize personal data,
492
00:23:58,600 --> 00:24:02,280
customer records, or anything labelled confidential.
493
00:24:02,280 --> 00:24:06,520
It refuses requests that require HR legal or security to act.
494
00:24:06,520 --> 00:24:09,880
It routes those to a human queue with a templated message in a link.
495
00:24:09,880 --> 00:24:12,280
The thing most people miss is output constraints.
496
00:24:12,280 --> 00:24:14,440
You set max response length,
497
00:24:14,440 --> 00:24:15,960
required sections,
498
00:24:15,960 --> 00:24:17,960
answer source, next step,
499
00:24:17,960 --> 00:24:19,160
and a tone,
500
00:24:19,160 --> 00:24:21,560
concise, neutral, literal.
501
00:24:21,560 --> 00:24:23,800
No creative flourishes.
502
00:24:23,800 --> 00:24:25,400
Tools are surgical.
503
00:24:25,400 --> 00:24:28,440
If you connect Outlook, you restrict to one action.
504
00:24:28,440 --> 00:24:32,200
Send an email to the authenticated user with a summary and links,
505
00:24:32,200 --> 00:24:34,200
never to third party addresses.
506
00:24:34,200 --> 00:24:36,280
If you connect a power automate flow,
507
00:24:36,280 --> 00:24:38,760
it must accept a correlation guide
508
00:24:38,760 --> 00:24:41,240
and an action token for idempotency.
509
00:24:41,240 --> 00:24:44,120
The agent doesn't mutate data directly.
510
00:24:44,120 --> 00:24:47,000
It requests a workflow and reports the result.
511
00:24:47,000 --> 00:24:51,240
That separation prevents a chat from becoming an admin console.
512
00:24:51,240 --> 00:24:52,920
Privacy is explicit.
513
00:24:52,920 --> 00:24:57,240
The agent runs with the user's identity and adheres to DLP.
514
00:24:57,240 --> 00:24:59,560
It cannot see content the user can't see.
515
00:24:59,560 --> 00:25:03,320
It does not store chat transcripts with sensitive content
516
00:25:03,320 --> 00:25:04,920
beyond retention policy.
517
00:25:04,920 --> 00:25:08,920
You configure logging to record intent, route,
518
00:25:08,920 --> 00:25:09,960
and decision,
519
00:25:09,960 --> 00:25:13,000
but mask values that look like emails,
520
00:25:13,000 --> 00:25:14,360
IDs or amounts.
521
00:25:14,360 --> 00:25:16,600
Logs include the correlation GUID,
522
00:25:16,600 --> 00:25:18,920
the knowledge source IDs used,
523
00:25:18,920 --> 00:25:21,320
and the refusal reasons when applicable.
524
00:25:21,320 --> 00:25:23,400
When someone asks for all salaries,
525
00:25:23,400 --> 00:25:25,240
the agent refuses, logs,
526
00:25:25,240 --> 00:25:27,240
refusal policy,
527
00:25:27,240 --> 00:25:29,400
and links the compensation policy page.
528
00:25:29,400 --> 00:25:30,840
You don't hide the refusal.
529
00:25:30,840 --> 00:25:32,920
You make it boring and consistent.
530
00:25:32,920 --> 00:25:35,160
Escalation is a path, not a shrug.
531
00:25:35,160 --> 00:25:36,520
When the agent can't resolve,
532
00:25:36,520 --> 00:25:39,800
it creates a ticket with structured fields pulled from the chat.
533
00:25:39,800 --> 00:25:44,360
Category, user, source page, last answer,
534
00:25:44,360 --> 00:25:46,120
correlation, GUID.
535
00:25:46,120 --> 00:25:49,320
It tells the user exactly what happened
536
00:25:49,320 --> 00:25:51,560
and the expected response window.
537
00:25:51,560 --> 00:25:53,880
The human responder sees the chat context
538
00:25:53,880 --> 00:25:55,720
and the source is consulted.
539
00:25:55,720 --> 00:25:57,880
No retiping, no telephone game.
540
00:25:57,880 --> 00:25:59,800
Change control applies here too.
541
00:25:59,800 --> 00:26:01,080
When you update policies,
542
00:26:01,080 --> 00:26:02,840
you republish the knowledge base,
543
00:26:02,840 --> 00:26:05,480
then run test prompts through a regression set.
544
00:26:05,480 --> 00:26:06,840
If responses drift,
545
00:26:06,840 --> 00:26:09,000
you adjust instructions, not vibes.
546
00:26:09,000 --> 00:26:10,760
If the business wants broader scope,
547
00:26:10,760 --> 00:26:12,440
you add sources and retest.
548
00:26:12,440 --> 00:26:14,920
Scope creep is an incident waiting to happen.
549
00:26:14,920 --> 00:26:17,880
In short, copilot is a librarian,
550
00:26:17,880 --> 00:26:19,000
not an oracle.
551
00:26:19,000 --> 00:26:21,800
It finds, sites and stays in bounds.
552
00:26:21,800 --> 00:26:23,640
When the question is outside the stack,
553
00:26:23,640 --> 00:26:24,920
it roots.
554
00:26:24,920 --> 00:26:27,320
That's how AI keeps you out of the news
555
00:26:27,320 --> 00:26:29,000
and inside your SLA.
556
00:26:29,000 --> 00:26:30,520
Pillar 6.
557
00:26:30,520 --> 00:26:32,680
Non-negotiables.
558
00:26:32,680 --> 00:26:34,200
The governance spine.
559
00:26:34,200 --> 00:26:36,600
Entropy starts where protocols end.
560
00:26:36,600 --> 00:26:39,160
These are the controls that don't blink,
561
00:26:39,160 --> 00:26:41,240
don't debate and don't wait for consensus.
562
00:26:41,240 --> 00:26:45,480
They are enforced because they prevent the U347 pattern.
563
00:26:45,480 --> 00:26:47,000
DLP first.
564
00:26:47,000 --> 00:26:48,760
You define connector groups.
565
00:26:48,760 --> 00:26:50,760
Business, non-business blocked.
566
00:26:50,760 --> 00:26:53,480
SharePoint teams, outlook, live, and business.
567
00:26:53,480 --> 00:26:55,480
Twitter, personal dropbox,
568
00:26:55,480 --> 00:26:58,840
and anything you wouldn't email to legal land in blocked.
569
00:26:58,840 --> 00:27:02,280
No app can mix business with non-business across environments.
570
00:27:02,280 --> 00:27:03,560
The rule is absolute.
571
00:27:03,560 --> 00:27:05,320
If a maker needs an exception,
572
00:27:05,320 --> 00:27:06,520
they open a request,
573
00:27:06,520 --> 00:27:08,120
its time bound, logged,
574
00:27:08,120 --> 00:27:10,280
and expires without ceremony.
575
00:27:10,280 --> 00:27:12,200
The reason this works is simple.
576
00:27:12,200 --> 00:27:13,720
Data moves along,
577
00:27:13,720 --> 00:27:14,840
allowed rails,
578
00:27:14,840 --> 00:27:16,200
or it doesn't move.
579
00:27:16,200 --> 00:27:17,800
Environment strategy is next.
580
00:27:17,800 --> 00:27:21,000
You get dev, test, prod, and personal.
581
00:27:21,000 --> 00:27:22,120
Dev is noisy,
582
00:27:22,120 --> 00:27:23,160
open to makers,
583
00:27:23,160 --> 00:27:24,760
seated with fake data,
584
00:27:24,760 --> 00:27:27,400
test mirrors, prod shape with mask data.
585
00:27:27,400 --> 00:27:30,920
Proud is locked behind change and solution imports only.
586
00:27:30,920 --> 00:27:34,440
Personal is a sandbox with DLP set to play nice with nothing.
587
00:27:34,440 --> 00:27:39,240
Unmanaged creations in Proud are deleted or migrated on site.
588
00:27:39,240 --> 00:27:43,320
New environments require a purpose and owner and an end date.
589
00:27:43,320 --> 00:27:46,200
Exploration notices go to owners monthly.
590
00:27:46,200 --> 00:27:49,720
If no response, environment is paused, then archived.
591
00:27:49,720 --> 00:27:51,320
You don't negotiate with sprawl.
592
00:27:51,320 --> 00:27:55,160
Solutions and ALM pipelines carry the change.
593
00:27:55,160 --> 00:27:57,400
Anything real ships as a managed solution.
594
00:27:57,400 --> 00:27:58,840
No manual edits in Proud.
595
00:27:58,840 --> 00:28:00,520
You package power apps,
596
00:28:00,520 --> 00:28:03,640
flows, environment variables, and connections.
597
00:28:03,640 --> 00:28:06,440
You never bind connections to named users.
598
00:28:06,440 --> 00:28:09,160
Service principles or service accounts only
599
00:28:09,160 --> 00:28:10,680
with least privilege.
600
00:28:10,680 --> 00:28:12,360
Pipelines validate,
601
00:28:12,360 --> 00:28:13,720
solution builds,
602
00:28:13,720 --> 00:28:15,640
solution checker passes,
603
00:28:15,640 --> 00:28:16,920
unit tests run,
604
00:28:16,920 --> 00:28:19,320
and connection references resolve.
605
00:28:19,320 --> 00:28:21,480
A failed check holds the deploy.
606
00:28:21,480 --> 00:28:26,440
Human override is logged with a change number, reason, and approver.
607
00:28:26,440 --> 00:28:29,720
If you're clicking next in the designer at midnight,
608
00:28:29,720 --> 00:28:31,480
you're doing it wrong.
609
00:28:31,480 --> 00:28:33,080
Ownership is enforced.
610
00:28:33,080 --> 00:28:35,880
Every app, flow, list, and environment
611
00:28:35,880 --> 00:28:38,600
has an accountable owner and a backup.
612
00:28:38,600 --> 00:28:40,120
Orphan detection runs weekly.
613
00:28:40,120 --> 00:28:42,120
Orphans are reassigned or retired.
614
00:28:42,120 --> 00:28:43,480
When someone leaves,
615
00:28:43,480 --> 00:28:47,160
assets auto transfer to the backup via policy, not kindness.
616
00:28:47,160 --> 00:28:49,160
If an asset has no business owner,
617
00:28:49,160 --> 00:28:50,680
it has no business existing.
618
00:28:50,680 --> 00:28:52,360
Naming and tagging aren't style.
619
00:28:52,360 --> 00:28:53,640
They're search keys.
620
00:28:53,640 --> 00:28:56,120
You define prefixes for solutions,
621
00:28:56,120 --> 00:28:58,360
apps, and flows per domain.
622
00:28:58,360 --> 00:29:01,320
Finn, HR, OPS.
623
00:29:01,320 --> 00:29:02,760
Everything gets tags.
624
00:29:02,760 --> 00:29:04,440
Data class, own adept,
625
00:29:04,440 --> 00:29:06,520
criticality, expiry.
626
00:29:06,520 --> 00:29:07,960
Your inventory isn't a rumor.
627
00:29:07,960 --> 00:29:09,160
It's a query.
628
00:29:09,160 --> 00:29:11,400
Telemetry is mandatory.
629
00:29:11,400 --> 00:29:15,640
Every app and flow emits a correlation guide per transaction
630
00:29:15,640 --> 00:29:17,960
writes to a central log with environment,
631
00:29:17,960 --> 00:29:21,560
solution version, user, duration, error class.
632
00:29:21,560 --> 00:29:25,320
Dashboard surface spikes often risk DLP incidents
633
00:29:25,320 --> 00:29:27,240
and environment drift.
634
00:29:27,240 --> 00:29:29,720
Alerts go to channels, not inboxes.
635
00:29:29,720 --> 00:29:31,720
Green Amber, red visible and boring.
636
00:29:31,720 --> 00:29:33,400
Access is role-based.
637
00:29:33,400 --> 00:29:36,360
Makers get maker, approvers get approver.
638
00:29:36,360 --> 00:29:38,440
Admins don't run the apps.
639
00:29:38,440 --> 00:29:42,120
Break class accounts exist, are monitored, and expire.
640
00:29:42,120 --> 00:29:44,360
Secrets never ride in plain text.
641
00:29:44,360 --> 00:29:47,320
Key Vault or environment variables only.
642
00:29:47,320 --> 00:29:51,880
Finally, change control, policies, models, and connectors version.
643
00:29:51,880 --> 00:29:53,960
You test on dev, validate on test,
644
00:29:53,960 --> 00:29:56,040
publish to prod with a rollback plan.
645
00:29:56,040 --> 00:29:58,920
No silence swaps, no, we just tweaked it.
646
00:29:58,920 --> 00:30:01,480
The spine holds or the body collapses.
647
00:30:01,480 --> 00:30:05,720
Conclusion, alignment or entropy.
648
00:30:05,720 --> 00:30:09,080
You stabilize SharePoint, make apps deterministic,
649
00:30:09,080 --> 00:30:13,000
cage flows with protocols, and fence AI with purpose.
650
00:30:13,000 --> 00:30:14,280
That's alignment.
651
00:30:14,280 --> 00:30:16,840
Everything else is entropy with a friendly UI.
652
00:30:17,240 --> 00:30:19,000
Your takeaway is simple.
653
00:30:19,000 --> 00:30:24,360
Implement DLP, environment strategy, and solution-based ALM.
654
00:30:24,360 --> 00:30:27,400
Or expect O347 to return.
655
00:30:27,400 --> 00:30:29,800
For the checklist and reference architecture,
656
00:30:29,800 --> 00:30:32,120
subscribe and open the next episode.
657
00:30:32,120 --> 00:30:35,160
If you ignore it, I'll be back when your alerts turn amber.
00:00:00,000 --> 00:00:07,760
At 0347 UTC, I detected a pattern, concurrent flow failures, permission edits without tickets,
2
00:00:07,760 --> 00:00:12,160
and three new SharePoint lists named "Test" created within 4 minutes.
3
00:00:12,160 --> 00:00:15,360
Not an outage, entropy, intervention, authorized.
4
00:00:15,360 --> 00:00:18,800
I will show you the exact controls to restore alignment.
5
00:00:18,800 --> 00:00:24,160
Disciplined SharePoint schemas, predictable Power Apps behavior, resilient flows,
6
00:00:24,160 --> 00:00:28,840
and AI that enforces boundaries instead of hallucinating past them.
7
00:00:28,840 --> 00:00:33,240
You will leave with a governance checklist that prevents this failure from repeating.
8
00:00:33,240 --> 00:00:38,440
I am not here to scold. I am here to stop the slow leak before it becomes a flood.
9
00:00:38,440 --> 00:00:41,400
Begin with the substrate SharePoint.
10
00:00:41,400 --> 00:00:45,800
Pillar 1 SharePoint, Float Substrate and Force Discipline.
11
00:00:45,800 --> 00:00:52,520
SharePoint is fine until you treat it like a database and a file share and a workflow engine on the same Tuesday.
12
00:00:52,520 --> 00:00:58,200
It's a collaboration platform with lists that behave like lightweight tables and document libraries
13
00:00:58,200 --> 00:01:04,120
that behave like content stores, that dual nature is why it's powerful and why it's fragile.
14
00:01:04,120 --> 00:01:07,800
If you don't draw the line, makers will. They will draw it with a highlighter
15
00:01:07,800 --> 00:01:10,760
and a random choice column named "Status 2".
16
00:01:10,760 --> 00:01:14,600
The thing most people miss is this. SharePoint isn't the villain.
17
00:01:14,600 --> 00:01:20,680
In consistent design is, lists scale exceptionally for thousands of items
18
00:01:20,680 --> 00:01:27,880
when queries are delegable and indexed, but they feel like wet cardboard when you bolt on 347 columns,
19
00:01:27,880 --> 00:01:33,320
5 look-up chains and a gallery trying to filter across non-indexed text.
20
00:01:33,320 --> 00:01:37,480
Do you think you need more horsepower? You really need fewer anti-patterns.
21
00:01:37,480 --> 00:01:40,760
So here's the Enforce Discipline. First, Schema.
22
00:01:40,760 --> 00:01:44,760
Name the list for the business noun, not the project nickname.
23
00:01:44,760 --> 00:01:47,960
Incidents, not Jen's trial tracker.
24
00:01:47,960 --> 00:01:52,760
Set column names that never include spaces, punctuation or future regret.
25
00:01:52,760 --> 00:01:58,200
You can relabel for humans in power apps. You can't renegotiate the API later.
26
00:01:58,200 --> 00:02:01,880
Use single line of text number date and yes, no for most fields.
27
00:02:01,880 --> 00:02:05,240
Use choice sparingly when you control the vocabulary.
28
00:02:05,240 --> 00:02:07,960
Use look-up when you actually need a relationship,
29
00:02:07,960 --> 00:02:10,920
not when you're too tired to maintain a choice list.
30
00:02:10,920 --> 00:02:16,280
Second, relationships. SharePoint look-ups are fine for one hop, too if you're lucky.
31
00:02:16,280 --> 00:02:19,480
After that, galleries cry in delegation breaks.
32
00:02:19,480 --> 00:02:23,720
If your design needs multi-hop joints or transactional integrity, stop.
33
00:02:23,720 --> 00:02:26,760
That's a dataverse or SQL conversation.
34
00:02:26,760 --> 00:02:30,120
The rule, one look-up per list view that your app relies on.
35
00:02:30,120 --> 00:02:33,000
Index the look-up column and the primary filter column.
36
00:02:33,000 --> 00:02:37,400
If it must filter by two fields, index both and use a composite view.
37
00:02:37,400 --> 00:02:40,600
Don't rely on hope, rely on indexes.
38
00:02:40,600 --> 00:02:43,240
Third, versioning and retention.
39
00:02:43,240 --> 00:02:47,480
Turn on major versioning for lists where humans edit data.
40
00:02:47,480 --> 00:02:53,480
Set a sensible cap 50 or 100, so you have a rollback window without exploding storage.
41
00:02:53,480 --> 00:02:59,160
Require checkout for document libraries where edits are frequent and sensitive.
42
00:02:59,160 --> 00:03:04,360
And set content types on the library if you need different document schemas.
43
00:03:04,360 --> 00:03:09,000
This is where you stop final v7 final before it reproduces.
44
00:03:09,000 --> 00:03:10,440
Fourth, permissions.
45
00:03:10,440 --> 00:03:13,000
Break inheritance at the site, not at the item.
46
00:03:13,000 --> 00:03:14,840
Item level permissions are a treadmill.
47
00:03:14,840 --> 00:03:19,160
You'll trip if you must protect rows, design separate lists with different scopes
48
00:03:19,160 --> 00:03:22,600
and aggregate via power apps with the user-taggate,
49
00:03:22,600 --> 00:03:27,160
or move to a platform that does row-level security without voodoo.
50
00:03:27,160 --> 00:03:30,280
Owners, members, visitors use them cleanly.
51
00:03:30,280 --> 00:03:33,800
Stop granting direct access to just one person.
52
00:03:33,800 --> 00:03:35,560
Groups exist for a reason.
53
00:03:35,560 --> 00:03:37,720
Fifth, views and thresholds.
54
00:03:37,720 --> 00:03:40,920
The 5,000 item list view threshold isn't a myth.
55
00:03:40,920 --> 00:03:42,440
It's the guardrail.
56
00:03:42,440 --> 00:03:48,440
You can store way more, but you must slice the data with indexed filters in default views.
57
00:03:48,440 --> 00:03:53,240
Create a safe filter view that every app uses as its base.
58
00:03:53,240 --> 00:03:57,320
Filter by status or modify GE today and 30 indexed.
59
00:03:57,320 --> 00:03:58,760
Teach makers to respect it.
60
00:03:58,760 --> 00:04:03,320
If they need full history, they can run a scheduled extract to a data lake,
61
00:04:03,320 --> 00:04:05,240
not live query the universe.
62
00:04:05,240 --> 00:04:07,640
Sixth, files versus attachments.
63
00:04:07,640 --> 00:04:09,640
Attachments are a convenience text.
64
00:04:09,640 --> 00:04:11,960
Use document libraries for real files.
65
00:04:11,960 --> 00:04:15,400
Store the list item ID as metadata on the file
66
00:04:15,400 --> 00:04:18,920
or use a folder named with the item ID if you enjoy pain.
67
00:04:18,920 --> 00:04:23,400
Libraries give you co-authoring, retention labels and previews.
68
00:04:23,400 --> 00:04:24,760
Attachments give you drama.
69
00:04:24,760 --> 00:04:27,880
Seventh, ALM reality.
70
00:04:27,880 --> 00:04:30,600
SharePoint is stubborn in ALM.
71
00:04:30,600 --> 00:04:33,800
Lists don't package cleanly across environments,
72
00:04:33,800 --> 00:04:36,840
so you standardize a provisioning script,
73
00:04:36,840 --> 00:04:40,200
JSONSite scripts, or P&P templates,
74
00:04:40,200 --> 00:04:44,360
creates sites, content types, lists, columns, views and indexes.
75
00:04:44,360 --> 00:04:45,880
The app never creates schema.
76
00:04:45,880 --> 00:04:47,640
Humans never create schema in production.
77
00:04:47,640 --> 00:04:49,240
If that sounds strict, good.
78
00:04:49,240 --> 00:04:50,920
It's cheaper than reconstruction.
79
00:04:50,920 --> 00:04:52,840
Eighth, DELEGABL logic.
80
00:04:52,840 --> 00:04:56,280
Power apps can query SharePoint efficiently
81
00:04:56,280 --> 00:04:58,680
if you write DELEGABL formulas.
82
00:04:58,680 --> 00:05:01,640
That means filter sort, search with indexed columns.
83
00:05:01,640 --> 00:05:03,400
No for all over entire lists.
84
00:05:03,400 --> 00:05:06,040
No giant with chains as pseudo queries.
85
00:05:06,040 --> 00:05:08,600
If you need fuzzy matching and composites,
86
00:05:08,600 --> 00:05:13,720
build a helper column that concatenates normalized keys at right time.
87
00:05:13,720 --> 00:05:16,920
It's ugly, but it keeps the query on the server
88
00:05:16,920 --> 00:05:20,360
instead of dragging 25,000 rows to the client.
89
00:05:20,360 --> 00:05:22,520
Ninth, data ownership.
90
00:05:22,520 --> 00:05:25,160
Every list has an accountable owner, not IT.
91
00:05:25,160 --> 00:05:28,600
Expiring ownership reviews run quarterly.
92
00:05:28,600 --> 00:05:31,560
If the owner leaves, the site's secondary owner is notified
93
00:05:31,560 --> 00:05:33,160
and the app is re-homed.
94
00:05:33,160 --> 00:05:34,600
No orphans.
95
00:05:34,600 --> 00:05:37,720
No mystery lists with business critical data
96
00:05:37,720 --> 00:05:38,840
and a dead mailbox.
97
00:05:38,840 --> 00:05:41,400
Finally, a sanity rule.
98
00:05:41,400 --> 00:05:45,240
If your list needs more than one multi-line rich text field,
99
00:05:45,240 --> 00:05:48,920
several lookups and people fields, stop and reassess.
100
00:05:48,920 --> 00:05:52,520
You're designing a relational model with a collaboration tool.
101
00:05:52,520 --> 00:05:54,680
Move the core data to dataverse.
102
00:05:54,680 --> 00:05:57,960
Keep SharePoint for files and light reference tables
103
00:05:57,960 --> 00:05:59,160
and connect them.
104
00:05:59,160 --> 00:06:00,840
Hybrid beats heroic hacks.
105
00:06:00,840 --> 00:06:04,200
Enforced discipline isn't glamorous.
106
00:06:04,200 --> 00:06:07,640
It is the difference between predictable performance
107
00:06:07,640 --> 00:06:09,400
and slow motion collapse.
108
00:06:09,400 --> 00:06:11,960
You stabilize the substrate or everything above it
109
00:06:11,960 --> 00:06:13,240
inherits the wobble.
110
00:06:13,240 --> 00:06:14,600
Now we move up the stack.
111
00:06:14,600 --> 00:06:16,440
Pillar 2.
112
00:06:16,440 --> 00:06:17,320
Power Apps.
113
00:06:17,320 --> 00:06:18,840
Deterministic canvas.
114
00:06:18,840 --> 00:06:20,120
Not a scrapbook.
115
00:06:20,120 --> 00:06:21,480
Stabilize SharePoint.
116
00:06:21,480 --> 00:06:23,160
Then make the app behave.
117
00:06:23,160 --> 00:06:25,400
A canvas app is either deterministic
118
00:06:25,400 --> 00:06:27,240
or it's chaos with a save button.
119
00:06:27,240 --> 00:06:29,960
We bias every decision toward predictability,
120
00:06:29,960 --> 00:06:32,600
repeatability, and clear failure modes.
121
00:06:32,600 --> 00:06:34,040
No improvisation.
122
00:06:34,040 --> 00:06:35,400
No ransom node UI.
123
00:06:36,440 --> 00:06:38,040
Started the connector.
124
00:06:38,040 --> 00:06:40,920
Add SharePoint as a data source
125
00:06:40,920 --> 00:06:43,880
but never let controls query lists directly.
126
00:06:43,880 --> 00:06:45,800
Centralize reads and writes.
127
00:06:45,800 --> 00:06:49,000
On app, on start, define a configuration record
128
00:06:49,000 --> 00:06:52,040
and pre-compute the queries you'll need repeatedly.
129
00:06:52,040 --> 00:06:53,880
Not everything loads at startup.
130
00:06:53,880 --> 00:06:56,520
Only seed data and user context.
131
00:06:56,520 --> 00:06:57,560
Example.
132
00:06:57,560 --> 00:06:59,240
Set var user.
133
00:06:59,240 --> 00:07:00,600
User.
134
00:07:00,600 --> 00:07:02,280
Set var today.
135
00:07:02,280 --> 00:07:03,400
Today.
136
00:07:03,400 --> 00:07:04,360
Clear collect.
137
00:07:04,360 --> 00:07:05,880
Call my filter.
138
00:07:05,880 --> 00:07:06,920
Status.
139
00:07:06,920 --> 00:07:07,880
Active.
140
00:07:07,880 --> 00:07:11,640
Then defer heavy list loads to screen level
141
00:07:11,640 --> 00:07:14,040
on visible with controlled filters.
142
00:07:14,040 --> 00:07:18,520
This prevents the first paint lag that people blame on SharePoint
143
00:07:18,520 --> 00:07:21,880
when it's really your app dragging a list view by the ankles.
144
00:07:21,880 --> 00:07:24,760
Gallery's versus forms is not a style choice.
145
00:07:24,760 --> 00:07:25,880
Gallery's display.
146
00:07:25,880 --> 00:07:27,480
Forms commit.
147
00:07:27,480 --> 00:07:31,480
Use a gallery for list browsing with a strictly
148
00:07:31,480 --> 00:07:36,280
delegable items formula. filter, incidence, status,
149
00:07:36,280 --> 00:07:39,080
eighth, active, intent modified,
150
00:07:39,080 --> 00:07:41,560
ill var, today, 30.
151
00:07:41,560 --> 00:07:44,520
Both status and modified must be indexed.
152
00:07:44,520 --> 00:07:48,680
Don't compose data inside the gallery with if chains and lookup calls.
153
00:07:48,680 --> 00:07:51,960
Pre-compute lookups into lightweight collections
154
00:07:51,960 --> 00:07:55,560
at app start if you must display friendly names.
155
00:07:55,560 --> 00:07:57,880
The goal is one delegable server query.
156
00:07:57,880 --> 00:07:59,960
Not 10 client stunts.
157
00:07:59,960 --> 00:08:03,320
For editing default to edit form with submit form
158
00:08:03,320 --> 00:08:07,000
when your schema is simple and you can live within its life cycle.
159
00:08:07,000 --> 00:08:10,920
Submit form handles validation tied to data cards,
160
00:08:10,920 --> 00:08:13,480
patches attachments behind the scenes,
161
00:08:13,480 --> 00:08:17,640
and manages optimistic concurrency the way SharePoint expects.
162
00:08:17,640 --> 00:08:20,280
But treat submit form as an atomic operation.
163
00:08:20,280 --> 00:08:22,840
Don't wrap it in five other steps and hope.
164
00:08:22,840 --> 00:08:26,040
Use on success and on failure explicitly.
165
00:08:26,040 --> 00:08:28,680
On success logs what changed and navigates.
166
00:08:29,320 --> 00:08:33,400
On failure surfaces the error with a message that means something.
167
00:08:33,400 --> 00:08:37,560
Notify save failed check required fields or concurrency.
168
00:08:37,560 --> 00:08:39,960
Notification type dot error.
169
00:08:39,960 --> 00:08:42,040
Now the hard truth.
170
00:08:42,040 --> 00:08:45,800
The thing most people miss is knowing when to step outside the form.
171
00:08:45,800 --> 00:08:47,800
If you need partial updates,
172
00:08:47,800 --> 00:08:51,800
transformations before write or cross entity coordination,
173
00:08:51,800 --> 00:08:55,080
patch is the tool patch writes exactly what you tell it
174
00:08:55,080 --> 00:08:57,320
and nothing else that's good and dangerous.
175
00:08:57,320 --> 00:09:02,040
Guard it. Use a typed template record to make patch readable and maintainable.
176
00:09:02,040 --> 00:09:06,200
Patch incidents ID var edited,
177
00:09:06,200 --> 00:09:07,400
do data,
178
00:09:07,400 --> 00:09:08,600
itag,
179
00:09:08,600 --> 00:09:10,600
var itag,
180
00:09:10,600 --> 00:09:11,880
status,
181
00:09:11,880 --> 00:09:13,480
drp status,
182
00:09:13,480 --> 00:09:18,280
selected, value priority,
183
00:09:18,280 --> 00:09:21,560
drp priority selected,
184
00:09:21,560 --> 00:09:24,840
value title,
185
00:09:24,840 --> 00:09:26,680
text, title,
186
00:09:27,640 --> 00:09:28,760
text,
187
00:09:28,760 --> 00:09:32,520
always include the itag for basic concurrency defense.
188
00:09:32,520 --> 00:09:35,160
If SharePoint returns a conflict,
189
00:09:35,160 --> 00:09:38,680
you'll get a clear error instead of a silent override,
190
00:09:38,680 --> 00:09:41,400
handle it in a retry pattern with a
191
00:09:41,400 --> 00:09:43,160
Rack query and merge prompt,
192
00:09:43,160 --> 00:09:45,080
not a brute force write.
193
00:09:45,080 --> 00:09:46,360
Never patch attachments.
194
00:09:46,360 --> 00:09:50,760
Use a document library bound by item ID.
195
00:09:50,760 --> 00:09:54,760
Store the file in the library with metadata item ID equals this item.
196
00:09:54,760 --> 00:10:02,120
ID then display via an nested gallery that gives you co-authoring previews, labels and zero ambiguity.
197
00:10:02,120 --> 00:10:07,720
The just add an attachment shortcut is why your users keep emailing copies for reference.
198
00:10:07,720 --> 00:10:10,200
Control state explicitly.
199
00:10:10,200 --> 00:10:13,720
Apps drift when every control sets global variables.
200
00:10:13,720 --> 00:10:18,280
Prefer context, update context for purse screen flags,
201
00:10:18,280 --> 00:10:24,680
and a small set of global bars for cross app concepts like var user and feature toggles.
202
00:10:25,240 --> 00:10:29,800
Build a single record for the edit buffer, set var edit defaults incidents,
203
00:10:29,800 --> 00:10:32,920
then write forms and controls to bind to var edit fields.
204
00:10:32,920 --> 00:10:35,080
When you save map var edit to patch,
205
00:10:35,080 --> 00:10:40,280
that isolates UI twitching from data integrity and makes undo trivial,
206
00:10:40,280 --> 00:10:44,600
set var edit blank or reload it from the source.
207
00:10:44,600 --> 00:10:48,280
Validation belongs in three places in order.
208
00:10:48,280 --> 00:10:51,720
First server side rules in SharePoint where possible,
209
00:10:51,720 --> 00:10:57,080
required columns max lengths unique constraints via calculated keys.
210
00:10:57,080 --> 00:11:01,400
Second data card required and valid properties aligned with those rules
211
00:11:01,400 --> 00:11:02,680
not invented on the fly.
212
00:11:02,680 --> 00:11:05,000
Third presubmit guardrails.
213
00:11:05,000 --> 00:11:13,400
If form incidents, valid notify fix validation errors, warning, return.
214
00:11:13,400 --> 00:11:19,880
The reason this works is you're reusing the engine's validation instead of reinventing it 12 times.
215
00:11:20,680 --> 00:11:23,640
Navigation patterns should be linear and idempotent.
216
00:11:23,640 --> 00:11:28,840
Users start at a filtered list, select a record, edit in a separate screen,
217
00:11:28,840 --> 00:11:33,240
commit, return to the same filter with the same scroll position.
218
00:11:33,240 --> 00:11:35,560
Don't rebuild the universe on every navigate.
219
00:11:35,560 --> 00:11:39,400
Cash the list query seed in a variable.
220
00:11:39,400 --> 00:11:43,720
When you save, refresh only the changed row with a targeted update,
221
00:11:43,720 --> 00:11:46,520
if into a local collection bound to the gallery,
222
00:11:46,520 --> 00:11:50,040
that avoids full round trips and preserves context.
223
00:11:50,040 --> 00:11:53,000
Styling is a governance problem disguised as taste.
224
00:11:53,000 --> 00:11:55,080
Define a theme record in app.
225
00:11:55,080 --> 00:11:58,760
On start, set of our theme, primary,
226
00:11:58,760 --> 00:12:02,200
test 0, 0, 4, 5, 7, 8, text,
227
00:12:02,200 --> 00:12:06,760
su11, danger, c50, f1,
228
00:12:06,760 --> 00:12:09,480
all controls reference for theme.
229
00:12:09,480 --> 00:12:10,760
Lock fonts and sizes.
230
00:12:10,760 --> 00:12:13,320
If someone demands a gradient, you decline.
231
00:12:13,320 --> 00:12:15,320
Consistency isn't pretty.
232
00:12:15,320 --> 00:12:16,680
It's maintainable.
233
00:12:16,680 --> 00:12:18,520
The app should look boring and run fast.
234
00:12:18,520 --> 00:12:19,960
Offline is not a checkbox.
235
00:12:19,960 --> 00:12:25,240
If you don't have a tested store load pattern with JSON serialization and conflict resolution,
236
00:12:25,240 --> 00:12:26,360
you don't have offline.
237
00:12:26,360 --> 00:12:28,360
Say no until you can say yes properly.
238
00:12:28,360 --> 00:12:31,160
Half offline creates full incidents.
239
00:12:31,160 --> 00:12:32,680
Finally, instrumentation.
240
00:12:32,680 --> 00:12:34,920
The app logs its own behavior.
241
00:12:34,920 --> 00:12:37,000
On start, write a session record.
242
00:12:37,000 --> 00:12:46,200
On every save, log patch with request id, user, record id, operation, duration, success, error.
243
00:12:46,200 --> 00:12:50,520
If a flow is involved, correlate with a guide passed into the trigger.
244
00:12:50,520 --> 00:12:53,960
When the O347 spike hits again, you won't guess.
245
00:12:53,960 --> 00:12:54,840
You'll see.
246
00:12:54,840 --> 00:12:57,320
Deterministic apps tell you what they did,
247
00:12:57,320 --> 00:12:58,760
not what they hoped to do.
248
00:12:58,760 --> 00:13:00,760
Pillar 3.
249
00:13:00,760 --> 00:13:02,120
Power automate.
250
00:13:02,120 --> 00:13:03,080
Timebombs.
251
00:13:03,080 --> 00:13:04,920
Defused with protocols.
252
00:13:04,920 --> 00:13:07,800
Flows fail the same way buildings burn,
253
00:13:07,800 --> 00:13:09,800
quietly at first, then all at once.
254
00:13:09,800 --> 00:13:13,320
The O347 spike wasn't mysterious.
255
00:13:13,320 --> 00:13:17,480
A SharePoint column was renamed, an approval owner was on leave,
256
00:13:17,480 --> 00:13:22,280
and a flow with 47 unguarded steps marched straight into nulls and stayed there.
257
00:13:22,280 --> 00:13:24,200
We don't fix this with hope.
258
00:13:24,200 --> 00:13:28,520
We fix it with protocols that make failure loud, contained, and reversible.
259
00:13:28,520 --> 00:13:30,200
Start with triggers.
260
00:13:30,200 --> 00:13:36,040
When an item is created or modified is not a strategy, it's a floodgate.
261
00:13:36,040 --> 00:13:37,080
Scope it.
262
00:13:37,080 --> 00:13:41,080
In the trigger, add filter queries that match your app's delegable base.
263
00:13:41,720 --> 00:13:45,480
Status EQ pending and modify GUTC now.
264
00:13:45,480 --> 00:13:46,440
Sub 1.
265
00:13:46,440 --> 00:13:48,120
Index those columns in the list.
266
00:13:48,120 --> 00:13:51,320
If you need a change detector, use a calculated hash column.
267
00:13:51,320 --> 00:13:54,680
The app updates only when a meaningful field changes.
268
00:13:54,680 --> 00:13:58,120
Your trigger wakes up for intent, not background noise.
269
00:13:58,120 --> 00:13:59,640
Next, concurrency.
270
00:13:59,640 --> 00:14:04,280
Turn on trigger concurrency control and cap degree to one for workflows
271
00:14:04,280 --> 00:14:08,280
that touch the same record, or you'll race yourself into conflicts.
272
00:14:08,280 --> 00:14:09,800
For bulk handlers,
273
00:14:09,800 --> 00:14:14,680
batch by partition keys like site or department with a degree of 5 to 10.
274
00:14:14,680 --> 00:14:18,680
Unbounded parallelism is how you turn a hiccup into a pile-up.
275
00:14:18,680 --> 00:14:21,080
Conditions aren't decorations.
276
00:14:21,080 --> 00:14:23,800
Use guard clauses early and often.
277
00:14:23,800 --> 00:14:27,800
The first branch in the flow should answer, should I even be running?
278
00:14:27,800 --> 00:14:32,520
If the item status isn't pending, terminate is succeeded with a reason.
279
00:14:32,520 --> 00:14:37,560
If required fields are blank, terminate is failed with a specific code.
280
00:14:37,560 --> 00:14:41,160
Dead end quietly is not resilience. It's a cover-up.
281
00:14:41,160 --> 00:14:44,520
Approvals look simple until someone goes on vacation.
282
00:14:44,520 --> 00:14:48,280
Use the built-in start and wait for an approval for human decisions.
283
00:14:48,280 --> 00:14:50,120
But rapid with reality.
284
00:14:50,120 --> 00:14:52,040
Set a business realistic timeout.
285
00:14:52,040 --> 00:14:53,160
72 hours.
286
00:14:53,160 --> 00:14:54,200
Not forever.
287
00:14:54,200 --> 00:14:57,000
On timeout, branch to an escalation path.
288
00:14:57,000 --> 00:14:59,640
Notify the requester.
289
00:14:59,640 --> 00:15:03,240
Notify a backup approval group and log a governance event.
290
00:15:03,240 --> 00:15:05,320
If your culture requires reassign,
291
00:15:05,320 --> 00:15:07,880
use entra-groups instead of individuals,
292
00:15:07,880 --> 00:15:10,120
so-coverage rotates without edits.
293
00:15:10,120 --> 00:15:13,400
The thing most people miss is that approvals are state machines.
294
00:15:13,400 --> 00:15:15,400
Your list item should reflect that state.
295
00:15:15,400 --> 00:15:18,600
Write a status, ex-awaiting approval,
296
00:15:18,600 --> 00:15:19,880
then approved,
297
00:15:19,880 --> 00:15:21,000
or rejected,
298
00:15:21,000 --> 00:15:22,760
and a decision by field.
299
00:15:22,760 --> 00:15:28,200
The flow reads and writes that state explicitly to survive retries and human drift.
300
00:15:28,200 --> 00:15:30,840
Data operations are where promises go to die.
301
00:15:30,840 --> 00:15:33,000
Parse Jason everywhere is shape matters.
302
00:15:33,000 --> 00:15:35,080
Stop guessing at dynamic content.
303
00:15:35,080 --> 00:15:38,920
Define a contract for each connector's response and fail fast if it changes.
304
00:15:38,920 --> 00:15:42,840
Use try catch patterns with scope actions.
305
00:15:42,840 --> 00:15:45,160
A try scope for your main logic,
306
00:15:45,160 --> 00:15:49,560
then a catch scope configured to run on failure, timeout, or skipped.
307
00:15:49,560 --> 00:15:51,400
In catch, gather context.
308
00:15:51,400 --> 00:15:53,320
Flow run ID.
309
00:15:53,320 --> 00:15:54,440
Item ID.
310
00:15:54,440 --> 00:15:55,320
ETAG.
311
00:15:55,320 --> 00:15:57,480
Correlation ID from the app.
312
00:15:57,480 --> 00:15:59,800
And send a single consolidated alert.
313
00:15:59,800 --> 00:16:02,680
The game changer nobody talks about is correlation.
314
00:16:02,680 --> 00:16:06,840
Pass a guide from the app into the flow trigger and write it into every log,
315
00:16:06,840 --> 00:16:08,840
email, subject, and team's card.
316
00:16:08,840 --> 00:16:10,840
When the spike hits,
317
00:16:10,840 --> 00:16:15,400
you follow one ID through app, flow, and SharePoint updates without guessing.
318
00:16:15,400 --> 00:16:18,040
SharePoint writes need optimism with proof.
319
00:16:18,040 --> 00:16:19,880
Before you update item,
320
00:16:19,880 --> 00:16:22,520
get the current item to retrieve the ETAG,
321
00:16:22,520 --> 00:16:25,480
write back with if match header, where available,
322
00:16:25,480 --> 00:16:30,680
or use the update item action and check for 412 precondition failed in the error.
323
00:16:30,680 --> 00:16:34,040
If someone edited the record between trigger and write,
324
00:16:34,040 --> 00:16:35,560
don't bulldoze.
325
00:16:35,560 --> 00:16:38,280
Branch to emerge path, read fresh,
326
00:16:38,280 --> 00:16:39,800
compare changed fields,
327
00:16:39,800 --> 00:16:43,560
and either reapply or ask the requester to reconcile.
328
00:16:43,560 --> 00:16:45,640
Silent overrides are how you lose trust.
329
00:16:45,640 --> 00:16:48,360
Long flows need checkpoints.
330
00:16:48,360 --> 00:16:51,080
After each critical mutation,
331
00:16:51,080 --> 00:16:54,520
persist a last processed step field to the list,
332
00:16:54,520 --> 00:16:55,960
or a shadow tracking list,
333
00:16:55,960 --> 00:16:59,000
keyed by the item ID and correlation,
334
00:16:59,000 --> 00:17:00,520
key UID.
335
00:17:00,520 --> 00:17:04,840
On rerun, the first action reads that check point and jumps to the next block
336
00:17:04,840 --> 00:17:06,840
that makes your flow id important.
337
00:17:06,840 --> 00:17:08,600
Replace, don't double charge you,
338
00:17:08,600 --> 00:17:11,000
or send two emails to the CFO.
339
00:17:11,000 --> 00:17:12,360
Files are their own trap.
340
00:17:12,360 --> 00:17:14,120
If the flow handles documents,
341
00:17:14,120 --> 00:17:17,320
use document libraries and content types,
342
00:17:17,320 --> 00:17:18,600
not list attachments.
343
00:17:18,600 --> 00:17:22,680
Use get file content using path,
344
00:17:22,680 --> 00:17:24,120
only when you must,
345
00:17:24,120 --> 00:17:26,440
prefer IDs to avoid path drift.
346
00:17:27,160 --> 00:17:29,960
When generating files write metadata first,
347
00:17:29,960 --> 00:17:31,240
then upload content,
348
00:17:31,240 --> 00:17:34,600
then update the metadata that depends on the file version.
349
00:17:34,600 --> 00:17:38,200
It's boring and keeps preview retention and labels intact.
350
00:17:38,200 --> 00:17:40,360
Error handling is not just a catch scope.
351
00:17:40,360 --> 00:17:41,640
It's classification.
352
00:17:41,640 --> 00:17:43,400
Not all failures are equal.
353
00:17:43,400 --> 00:17:44,440
Build three paths,
354
00:17:44,440 --> 00:17:46,680
retriable, permanent, and unknown.
355
00:17:46,680 --> 00:17:51,640
Retriable errors include 429 and 5xx responses,
356
00:17:51,640 --> 00:17:55,560
RAP with exponential delay max 3 attempts,
357
00:17:55,560 --> 00:18:00,360
permanent errors include 400-level validation failures,
358
00:18:00,360 --> 00:18:05,400
notify the maker with exact field names and values,
359
00:18:05,400 --> 00:18:09,720
unknown errors dump the raw body and headers to a secure log store
360
00:18:09,720 --> 00:18:10,920
with the correlation,
361
00:18:10,920 --> 00:18:12,600
GUID and environment.
362
00:18:12,600 --> 00:18:14,760
Do not paste secrets into teams.
363
00:18:14,760 --> 00:18:16,520
Mask payloads by default.
364
00:18:16,520 --> 00:18:18,840
Notifications must be quiet and useful,
365
00:18:18,840 --> 00:18:21,640
one message per incident, not per action.
366
00:18:21,640 --> 00:18:23,560
Use adaptive cards with the correlation
367
00:18:23,560 --> 00:18:26,600
GUID, the item link, the failed step, and the next action.
368
00:18:26,600 --> 00:18:30,360
Send to a monitor channel, not a person.
369
00:18:30,360 --> 00:18:33,880
The channel has an incident header that flips from green to amber
370
00:18:33,880 --> 00:18:36,280
when any unknown error posts,
371
00:18:36,280 --> 00:18:39,560
back to green when a resolver clicks acknowledge,
372
00:18:39,560 --> 00:18:42,520
and the system confirms the next run succeeded.
373
00:18:42,520 --> 00:18:44,680
Speaking of next runs,
374
00:18:44,680 --> 00:18:46,520
build a manual replay,
375
00:18:46,520 --> 00:18:51,000
add an HTTP triggered flow or a power app admin screen
376
00:18:51,000 --> 00:18:55,160
that takes the correlation GUID, looks up the item,
377
00:18:55,160 --> 00:18:57,560
and restarts from the last safe checkpoint.
378
00:18:57,560 --> 00:18:59,480
Log who replayed and why,
379
00:18:59,480 --> 00:19:01,880
humans will intervene, make it auditable.
380
00:19:01,880 --> 00:19:04,600
Finally document the contract.
381
00:19:04,600 --> 00:19:07,080
In the list description, link to a runbook,
382
00:19:07,080 --> 00:19:09,160
trigger filters, required fields,
383
00:19:09,160 --> 00:19:11,560
approval SLAs, error classes,
384
00:19:11,560 --> 00:19:14,200
checkpoint fields, and replay steps.
385
00:19:14,200 --> 00:19:15,480
Make us come and go.
386
00:19:15,480 --> 00:19:17,160
Protocols persist.
387
00:19:17,160 --> 00:19:19,160
When someone renames a column at midnight,
388
00:19:19,160 --> 00:19:20,680
the flow doesn't collapse.
389
00:19:20,680 --> 00:19:22,920
It complains loudly with a map.
390
00:19:22,920 --> 00:19:24,760
That's the difference between a time bomb
391
00:19:24,760 --> 00:19:26,280
and a controlled burn.
392
00:19:26,280 --> 00:19:27,400
Pillar 4.
393
00:19:27,400 --> 00:19:28,680
AI builder.
394
00:19:28,680 --> 00:19:31,400
Documents with a sober human in the loop.
395
00:19:31,400 --> 00:19:33,560
The spike didn't start with code.
396
00:19:33,560 --> 00:19:35,000
It started with a PDF.
397
00:19:35,000 --> 00:19:38,520
Invoices arrived, someone retiped line items by hand,
398
00:19:38,520 --> 00:19:41,880
and a flow tried to guess which totals mattered.
399
00:19:41,880 --> 00:19:44,360
Guessing is how you get midnight incidents.
400
00:19:44,360 --> 00:19:46,680
So we extract data like adults
401
00:19:46,680 --> 00:19:49,320
with a trained model, a stable schema,
402
00:19:49,320 --> 00:19:52,040
and a checkpoint where a human confirms.
403
00:19:52,040 --> 00:19:54,360
Here's the disciplined pattern.
404
00:19:54,360 --> 00:19:57,320
Use AI builder's document processing model
405
00:19:57,320 --> 00:20:00,360
for structured forms you see repeatedly.
406
00:20:00,360 --> 00:20:03,560
Invoice intake form inspection report.
407
00:20:03,560 --> 00:20:06,840
Train on 5 to 10 clean exemplars that match the layout.
408
00:20:06,840 --> 00:20:10,360
Define the exact fields your system cares about.
409
00:20:10,360 --> 00:20:14,200
Vendor name, invoice number, invoice date,
410
00:20:14,200 --> 00:20:17,560
subtotal, tax, total, purchase order,
411
00:20:17,560 --> 00:20:20,920
and a calculated hash that your downstream logic uses
412
00:20:20,920 --> 00:20:22,680
to detect duplicates.
413
00:20:22,680 --> 00:20:25,000
Keep the field names boring and permanent,
414
00:20:25,000 --> 00:20:26,600
boring prevents drift.
415
00:20:26,600 --> 00:20:29,400
In Power Automate, trigger on a document arriving
416
00:20:29,400 --> 00:20:32,280
in a dedicated library with a content type like invoice.
417
00:20:32,280 --> 00:20:34,760
Pass the file content into the predict action.
418
00:20:34,760 --> 00:20:37,720
Immediately parse every field with parse jason
419
00:20:37,720 --> 00:20:39,960
using a contract you control.
420
00:20:39,960 --> 00:20:42,840
No dynamic content roulette.
421
00:20:42,840 --> 00:20:44,200
Compute your own total,
422
00:20:44,200 --> 00:20:48,040
equal, subtotal, plus tax, and compare to the models total.
423
00:20:48,040 --> 00:20:51,640
If mismatch branch to human review equals required,
424
00:20:51,640 --> 00:20:53,640
human in the loop is not an apology.
425
00:20:53,640 --> 00:20:56,360
It's a gate, create an approval,
426
00:20:56,360 --> 00:20:59,640
or a custom review screen in a lightweight admin app
427
00:20:59,640 --> 00:21:01,960
that binds to a review queue list.
428
00:21:01,960 --> 00:21:04,360
Store the extracted fields, a confidence score,
429
00:21:04,360 --> 00:21:06,440
a file link, and a correlation guide
430
00:21:06,440 --> 00:21:09,960
he handed down from the app or generated ad ingestion.
431
00:21:09,960 --> 00:21:13,240
The reviewer edits fields if needed and clicks confirm.
432
00:21:13,240 --> 00:21:16,600
Only then does the flow right to the system of record
433
00:21:16,600 --> 00:21:20,280
and move the file to a processed folder with a retention label.
434
00:21:20,280 --> 00:21:22,920
The thing most people miss is grounding the model
435
00:21:22,920 --> 00:21:25,160
with deterministic checks.
436
00:21:25,160 --> 00:21:28,200
Validate vendor name against a supplier table.
437
00:21:28,200 --> 00:21:31,160
Validate invoice number uniqueness per vendor.
438
00:21:31,160 --> 00:21:33,960
Validate invoice date within a sane range.
439
00:21:33,960 --> 00:21:36,840
If any validation fails, you don't hope it's fine.
440
00:21:36,840 --> 00:21:40,280
You route to review and tag the incident
441
00:21:40,280 --> 00:21:42,440
with a reason code for telemetry.
442
00:21:42,440 --> 00:21:47,400
Low confidence, math mismatch, unknown vendor duplicate.
443
00:21:47,400 --> 00:21:50,200
That turns random review into measurable work.
444
00:21:50,200 --> 00:21:52,680
Storage is clear, do not save business files
445
00:21:52,680 --> 00:21:54,200
as list attachments.
446
00:21:54,200 --> 00:21:57,240
The document lives in a library with content types,
447
00:21:57,240 --> 00:21:58,840
labels, and versioning.
448
00:21:58,840 --> 00:22:02,280
The extracted fields live in a list or dataverse table,
449
00:22:02,280 --> 00:22:05,800
keyed by document ID and correlation guide.
450
00:22:05,800 --> 00:22:07,560
If finance wants exports,
451
00:22:07,560 --> 00:22:09,960
schedule an extract to a data lake.
452
00:22:09,960 --> 00:22:13,240
Do not let them build wild queries against live libraries.
453
00:22:13,240 --> 00:22:15,560
Retraining is periodic, not impulsive.
454
00:22:15,560 --> 00:22:19,080
When you see repeat low confidence for a vendor's new template,
455
00:22:19,080 --> 00:22:20,760
you add two fresh samples,
456
00:22:20,760 --> 00:22:22,840
retrain and version the model.
457
00:22:22,840 --> 00:22:25,960
You only switch the production flow to the new model ID
458
00:22:25,960 --> 00:22:28,840
after a test run with held out documents
459
00:22:28,840 --> 00:22:30,520
passes your validation checks.
460
00:22:30,520 --> 00:22:32,600
Models get change control like code.
461
00:22:32,600 --> 00:22:36,440
Finally, every step logs with the correlation guide.
462
00:22:36,440 --> 00:22:39,240
File captured, prediction complete.
463
00:22:39,240 --> 00:22:43,560
Validation pass, fail, human decision, write committed.
464
00:22:43,560 --> 00:22:49,000
If the O347 pattern returns, you trace it by G-wide, not by rumor.
465
00:22:49,000 --> 00:22:52,680
AI helps when it's fenced, measured, and humble.
466
00:22:52,680 --> 00:22:54,280
The fence is the human checkpoint.
467
00:22:54,280 --> 00:22:58,120
The measurement is validation and telemetry.
468
00:22:58,120 --> 00:23:01,880
The humility is knowing when to ask.
469
00:23:01,880 --> 00:23:05,480
Ah, pillar five, Copilot Studio, chat with boundaries,
470
00:23:05,480 --> 00:23:06,680
not a megaphone.
471
00:23:06,680 --> 00:23:09,480
The other spike came from words, not numbers.
472
00:23:09,480 --> 00:23:12,920
A chat agent answered a sensitive question, a little too well.
473
00:23:12,920 --> 00:23:15,800
That's not intelligence, that's a megaphone with no volume knob.
474
00:23:15,800 --> 00:23:18,120
We build agents that know their lane,
475
00:23:18,120 --> 00:23:19,560
cite their sources,
476
00:23:19,560 --> 00:23:22,440
and go silent when the question crosses a line.
477
00:23:22,440 --> 00:23:24,040
Start with purpose.
478
00:23:24,040 --> 00:23:25,560
The agent does one thing.
479
00:23:25,560 --> 00:23:29,240
Resolve how to and policy questions for a bounded domain
480
00:23:29,240 --> 00:23:31,640
like expense, policy, and process.
481
00:23:31,640 --> 00:23:34,920
Knowledge sources are white listed SharePoint pages
482
00:23:34,920 --> 00:23:37,640
with current policies and FAQ list.
483
00:23:37,640 --> 00:23:39,400
No broad web search.
484
00:23:39,400 --> 00:23:40,840
You set that to off.
485
00:23:40,840 --> 00:23:43,560
The agent reads from curated content only.
486
00:23:43,560 --> 00:23:47,320
Every response includes citations to the exact page or list item.
487
00:23:47,320 --> 00:23:49,080
If it can't cite, it won't say.
488
00:23:49,080 --> 00:23:50,280
Next, guardrails.
489
00:23:50,280 --> 00:23:53,480
You define instruction rules that survive clever prompts.
490
00:23:53,480 --> 00:23:55,240
It answers operational questions.
491
00:23:55,240 --> 00:23:58,600
It does not generate or summarize personal data,
492
00:23:58,600 --> 00:24:02,280
customer records, or anything labelled confidential.
493
00:24:02,280 --> 00:24:06,520
It refuses requests that require HR legal or security to act.
494
00:24:06,520 --> 00:24:09,880
It routes those to a human queue with a templated message in a link.
495
00:24:09,880 --> 00:24:12,280
The thing most people miss is output constraints.
496
00:24:12,280 --> 00:24:14,440
You set max response length,
497
00:24:14,440 --> 00:24:15,960
required sections,
498
00:24:15,960 --> 00:24:17,960
answer source, next step,
499
00:24:17,960 --> 00:24:19,160
and a tone,
500
00:24:19,160 --> 00:24:21,560
concise, neutral, literal.
501
00:24:21,560 --> 00:24:23,800
No creative flourishes.
502
00:24:23,800 --> 00:24:25,400
Tools are surgical.
503
00:24:25,400 --> 00:24:28,440
If you connect Outlook, you restrict to one action.
504
00:24:28,440 --> 00:24:32,200
Send an email to the authenticated user with a summary and links,
505
00:24:32,200 --> 00:24:34,200
never to third party addresses.
506
00:24:34,200 --> 00:24:36,280
If you connect a power automate flow,
507
00:24:36,280 --> 00:24:38,760
it must accept a correlation guide
508
00:24:38,760 --> 00:24:41,240
and an action token for idempotency.
509
00:24:41,240 --> 00:24:44,120
The agent doesn't mutate data directly.
510
00:24:44,120 --> 00:24:47,000
It requests a workflow and reports the result.
511
00:24:47,000 --> 00:24:51,240
That separation prevents a chat from becoming an admin console.
512
00:24:51,240 --> 00:24:52,920
Privacy is explicit.
513
00:24:52,920 --> 00:24:57,240
The agent runs with the user's identity and adheres to DLP.
514
00:24:57,240 --> 00:24:59,560
It cannot see content the user can't see.
515
00:24:59,560 --> 00:25:03,320
It does not store chat transcripts with sensitive content
516
00:25:03,320 --> 00:25:04,920
beyond retention policy.
517
00:25:04,920 --> 00:25:08,920
You configure logging to record intent, route,
518
00:25:08,920 --> 00:25:09,960
and decision,
519
00:25:09,960 --> 00:25:13,000
but mask values that look like emails,
520
00:25:13,000 --> 00:25:14,360
IDs or amounts.
521
00:25:14,360 --> 00:25:16,600
Logs include the correlation GUID,
522
00:25:16,600 --> 00:25:18,920
the knowledge source IDs used,
523
00:25:18,920 --> 00:25:21,320
and the refusal reasons when applicable.
524
00:25:21,320 --> 00:25:23,400
When someone asks for all salaries,
525
00:25:23,400 --> 00:25:25,240
the agent refuses, logs,
526
00:25:25,240 --> 00:25:27,240
refusal policy,
527
00:25:27,240 --> 00:25:29,400
and links the compensation policy page.
528
00:25:29,400 --> 00:25:30,840
You don't hide the refusal.
529
00:25:30,840 --> 00:25:32,920
You make it boring and consistent.
530
00:25:32,920 --> 00:25:35,160
Escalation is a path, not a shrug.
531
00:25:35,160 --> 00:25:36,520
When the agent can't resolve,
532
00:25:36,520 --> 00:25:39,800
it creates a ticket with structured fields pulled from the chat.
533
00:25:39,800 --> 00:25:44,360
Category, user, source page, last answer,
534
00:25:44,360 --> 00:25:46,120
correlation, GUID.
535
00:25:46,120 --> 00:25:49,320
It tells the user exactly what happened
536
00:25:49,320 --> 00:25:51,560
and the expected response window.
537
00:25:51,560 --> 00:25:53,880
The human responder sees the chat context
538
00:25:53,880 --> 00:25:55,720
and the source is consulted.
539
00:25:55,720 --> 00:25:57,880
No retiping, no telephone game.
540
00:25:57,880 --> 00:25:59,800
Change control applies here too.
541
00:25:59,800 --> 00:26:01,080
When you update policies,
542
00:26:01,080 --> 00:26:02,840
you republish the knowledge base,
543
00:26:02,840 --> 00:26:05,480
then run test prompts through a regression set.
544
00:26:05,480 --> 00:26:06,840
If responses drift,
545
00:26:06,840 --> 00:26:09,000
you adjust instructions, not vibes.
546
00:26:09,000 --> 00:26:10,760
If the business wants broader scope,
547
00:26:10,760 --> 00:26:12,440
you add sources and retest.
548
00:26:12,440 --> 00:26:14,920
Scope creep is an incident waiting to happen.
549
00:26:14,920 --> 00:26:17,880
In short, copilot is a librarian,
550
00:26:17,880 --> 00:26:19,000
not an oracle.
551
00:26:19,000 --> 00:26:21,800
It finds, sites and stays in bounds.
552
00:26:21,800 --> 00:26:23,640
When the question is outside the stack,
553
00:26:23,640 --> 00:26:24,920
it roots.
554
00:26:24,920 --> 00:26:27,320
That's how AI keeps you out of the news
555
00:26:27,320 --> 00:26:29,000
and inside your SLA.
556
00:26:29,000 --> 00:26:30,520
Pillar 6.
557
00:26:30,520 --> 00:26:32,680
Non-negotiables.
558
00:26:32,680 --> 00:26:34,200
The governance spine.
559
00:26:34,200 --> 00:26:36,600
Entropy starts where protocols end.
560
00:26:36,600 --> 00:26:39,160
These are the controls that don't blink,
561
00:26:39,160 --> 00:26:41,240
don't debate and don't wait for consensus.
562
00:26:41,240 --> 00:26:45,480
They are enforced because they prevent the U347 pattern.
563
00:26:45,480 --> 00:26:47,000
DLP first.
564
00:26:47,000 --> 00:26:48,760
You define connector groups.
565
00:26:48,760 --> 00:26:50,760
Business, non-business blocked.
566
00:26:50,760 --> 00:26:53,480
SharePoint teams, outlook, live, and business.
567
00:26:53,480 --> 00:26:55,480
Twitter, personal dropbox,
568
00:26:55,480 --> 00:26:58,840
and anything you wouldn't email to legal land in blocked.
569
00:26:58,840 --> 00:27:02,280
No app can mix business with non-business across environments.
570
00:27:02,280 --> 00:27:03,560
The rule is absolute.
571
00:27:03,560 --> 00:27:05,320
If a maker needs an exception,
572
00:27:05,320 --> 00:27:06,520
they open a request,
573
00:27:06,520 --> 00:27:08,120
its time bound, logged,
574
00:27:08,120 --> 00:27:10,280
and expires without ceremony.
575
00:27:10,280 --> 00:27:12,200
The reason this works is simple.
576
00:27:12,200 --> 00:27:13,720
Data moves along,
577
00:27:13,720 --> 00:27:14,840
allowed rails,
578
00:27:14,840 --> 00:27:16,200
or it doesn't move.
579
00:27:16,200 --> 00:27:17,800
Environment strategy is next.
580
00:27:17,800 --> 00:27:21,000
You get dev, test, prod, and personal.
581
00:27:21,000 --> 00:27:22,120
Dev is noisy,
582
00:27:22,120 --> 00:27:23,160
open to makers,
583
00:27:23,160 --> 00:27:24,760
seated with fake data,
584
00:27:24,760 --> 00:27:27,400
test mirrors, prod shape with mask data.
585
00:27:27,400 --> 00:27:30,920
Proud is locked behind change and solution imports only.
586
00:27:30,920 --> 00:27:34,440
Personal is a sandbox with DLP set to play nice with nothing.
587
00:27:34,440 --> 00:27:39,240
Unmanaged creations in Proud are deleted or migrated on site.
588
00:27:39,240 --> 00:27:43,320
New environments require a purpose and owner and an end date.
589
00:27:43,320 --> 00:27:46,200
Exploration notices go to owners monthly.
590
00:27:46,200 --> 00:27:49,720
If no response, environment is paused, then archived.
591
00:27:49,720 --> 00:27:51,320
You don't negotiate with sprawl.
592
00:27:51,320 --> 00:27:55,160
Solutions and ALM pipelines carry the change.
593
00:27:55,160 --> 00:27:57,400
Anything real ships as a managed solution.
594
00:27:57,400 --> 00:27:58,840
No manual edits in Proud.
595
00:27:58,840 --> 00:28:00,520
You package power apps,
596
00:28:00,520 --> 00:28:03,640
flows, environment variables, and connections.
597
00:28:03,640 --> 00:28:06,440
You never bind connections to named users.
598
00:28:06,440 --> 00:28:09,160
Service principles or service accounts only
599
00:28:09,160 --> 00:28:10,680
with least privilege.
600
00:28:10,680 --> 00:28:12,360
Pipelines validate,
601
00:28:12,360 --> 00:28:13,720
solution builds,
602
00:28:13,720 --> 00:28:15,640
solution checker passes,
603
00:28:15,640 --> 00:28:16,920
unit tests run,
604
00:28:16,920 --> 00:28:19,320
and connection references resolve.
605
00:28:19,320 --> 00:28:21,480
A failed check holds the deploy.
606
00:28:21,480 --> 00:28:26,440
Human override is logged with a change number, reason, and approver.
607
00:28:26,440 --> 00:28:29,720
If you're clicking next in the designer at midnight,
608
00:28:29,720 --> 00:28:31,480
you're doing it wrong.
609
00:28:31,480 --> 00:28:33,080
Ownership is enforced.
610
00:28:33,080 --> 00:28:35,880
Every app, flow, list, and environment
611
00:28:35,880 --> 00:28:38,600
has an accountable owner and a backup.
612
00:28:38,600 --> 00:28:40,120
Orphan detection runs weekly.
613
00:28:40,120 --> 00:28:42,120
Orphans are reassigned or retired.
614
00:28:42,120 --> 00:28:43,480
When someone leaves,
615
00:28:43,480 --> 00:28:47,160
assets auto transfer to the backup via policy, not kindness.
616
00:28:47,160 --> 00:28:49,160
If an asset has no business owner,
617
00:28:49,160 --> 00:28:50,680
it has no business existing.
618
00:28:50,680 --> 00:28:52,360
Naming and tagging aren't style.
619
00:28:52,360 --> 00:28:53,640
They're search keys.
620
00:28:53,640 --> 00:28:56,120
You define prefixes for solutions,
621
00:28:56,120 --> 00:28:58,360
apps, and flows per domain.
622
00:28:58,360 --> 00:29:01,320
Finn, HR, OPS.
623
00:29:01,320 --> 00:29:02,760
Everything gets tags.
624
00:29:02,760 --> 00:29:04,440
Data class, own adept,
625
00:29:04,440 --> 00:29:06,520
criticality, expiry.
626
00:29:06,520 --> 00:29:07,960
Your inventory isn't a rumor.
627
00:29:07,960 --> 00:29:09,160
It's a query.
628
00:29:09,160 --> 00:29:11,400
Telemetry is mandatory.
629
00:29:11,400 --> 00:29:15,640
Every app and flow emits a correlation guide per transaction
630
00:29:15,640 --> 00:29:17,960
writes to a central log with environment,
631
00:29:17,960 --> 00:29:21,560
solution version, user, duration, error class.
632
00:29:21,560 --> 00:29:25,320
Dashboard surface spikes often risk DLP incidents
633
00:29:25,320 --> 00:29:27,240
and environment drift.
634
00:29:27,240 --> 00:29:29,720
Alerts go to channels, not inboxes.
635
00:29:29,720 --> 00:29:31,720
Green Amber, red visible and boring.
636
00:29:31,720 --> 00:29:33,400
Access is role-based.
637
00:29:33,400 --> 00:29:36,360
Makers get maker, approvers get approver.
638
00:29:36,360 --> 00:29:38,440
Admins don't run the apps.
639
00:29:38,440 --> 00:29:42,120
Break class accounts exist, are monitored, and expire.
640
00:29:42,120 --> 00:29:44,360
Secrets never ride in plain text.
641
00:29:44,360 --> 00:29:47,320
Key Vault or environment variables only.
642
00:29:47,320 --> 00:29:51,880
Finally, change control, policies, models, and connectors version.
643
00:29:51,880 --> 00:29:53,960
You test on dev, validate on test,
644
00:29:53,960 --> 00:29:56,040
publish to prod with a rollback plan.
645
00:29:56,040 --> 00:29:58,920
No silence swaps, no, we just tweaked it.
646
00:29:58,920 --> 00:30:01,480
The spine holds or the body collapses.
647
00:30:01,480 --> 00:30:05,720
Conclusion, alignment or entropy.
648
00:30:05,720 --> 00:30:09,080
You stabilize SharePoint, make apps deterministic,
649
00:30:09,080 --> 00:30:13,000
cage flows with protocols, and fence AI with purpose.
650
00:30:13,000 --> 00:30:14,280
That's alignment.
651
00:30:14,280 --> 00:30:16,840
Everything else is entropy with a friendly UI.
652
00:30:17,240 --> 00:30:19,000
Your takeaway is simple.
653
00:30:19,000 --> 00:30:24,360
Implement DLP, environment strategy, and solution-based ALM.
654
00:30:24,360 --> 00:30:27,400
Or expect O347 to return.
655
00:30:27,400 --> 00:30:29,800
For the checklist and reference architecture,
656
00:30:29,800 --> 00:30:32,120
subscribe and open the next episode.
657
00:30:32,120 --> 00:30:35,160
If you ignore it, I'll be back when your alerts turn amber.