Exam mode
Exam mode revokes the coaching toolset — the agent cannot hint, coach, or reveal while the clock runs.
Dataverse plugin execution: the pipeline, images, and the difference between a veto and a side effect. The site grades; the agent coaches through the tools the roster currently permits.
phase: lessonA Dataverse plugin is a .NET class that implements IPlugin. The platform constructs it and calls Execute(IServiceProvider) when a registered message reaches the event pipeline. That pipeline lives on the server, inside the Dataverse organization service. It is not the canvas-app formula engine, not a model-driven form script, and not a Power Automate flow. Those surfaces can run complementary checks, but they are not the same transaction and they are not on the same call path.
Registration is what binds the class to traffic. In the Plugin Registration Tool (or equivalent solution metadata) you choose the message (Update, Create, Delete, and so on), the primary entity, the pipeline stage, and whether the step is synchronous. You also choose the filtering attributes: an Update step that lists creditlimit will not fire when a caller changes telephone1 alone. If the rule must hold for every writer, the step has to match the messages those writers actually send.
This is why client-side enforcement is not a substitute for a plugin. A canvas app OnSave formula, a business rule, or a form library can improve the interactive experience, but a Web API PATCH, an SDK UpdateRequest, an Import, or another plugin writing through IOrganizationService never loads that form. If the credit-limit rule is not in the pipeline, those callers skip it. Server-side registration is how you put a rule on the platform's own front door.
The event pipeline is a sequence of stages around the core database operation. Pre-validation is stage 10. It runs before the transaction for the request has started, which makes it a good place for cheap argument checks that should fail fast. Because it is outside the transaction, work you do here is not automatically rolled back with the core operation, and you should not treat it as a place to write dependent rows that must commit or fail with the target record.
Pre-operation is stage 20. For a synchronous step it runs inside the transaction, after security and validation, and before the core operation (stage 30) writes the row. Throwing InvalidPluginExecutionException here cancels the core operation and rolls the transaction back. You may also mutate the Target Entity so the core operation writes different values than the caller sent. That is the natural home for a credit-limit veto: you still have a chance to stop the write, and you share fate with it.
Post-operation is stage 40, after the core operation. A synchronous post-operation step is still inside the transaction; an asynchronous one is not — it is queued after the transaction commits. Use post-operation for work that needs the persisted row (sharing, related-record creates that should see the new id) and use asynchronous post-operation for side effects that must not hold the user's request open. The stage you pick is a transaction design, not a style preference.
IPluginExecutionContext is the plugin's view of the message. InputParameters["Target"] is the inbound payload: for Update, an Entity that contains the attributes the caller supplied, not a fully loaded row. ParentContext, MessageName, PrimaryEntityName, Depth, and UserId tell you who called, on which message, and whether you are already inside another plugin. Depth is the usual guard against infinite update loops when your plugin writes back to Dataverse.
Images are snapshots the platform takes because you asked it to, on the plugin step. A pre-image is the record as it existed before the core operation, limited to the columns you registered. A post-image is the record after the core operation. Neither image is a live IOrganizationService retrieve. They do not change if another thread updates the row, and they do not include columns you omitted from the image registration. If creditlimit is not in the pre-image, it is not there — even though the table still has a value.
The common failure is to treat Target as the pre-update row. Target on Update is a patch. If the caller sends only transactionamount, Target["creditlimit"] is missing; the prior balance is in the pre-image (or in a retrieve you explicitly issue). If the caller does send creditlimit, that value is the proposed new amount, not the previous one. Pre-images exist so you can compare before and after without guessing which attributes arrived in the payload.
A synchronous plugin runs on the request thread, inside the pipeline stage you registered, before the caller receives a response. It can throw and, in pre-operation or synchronous post-operation, participate in the request transaction. It is also budgeted: the platform enforces a two-minute execution limit, and every millisecond you spend is latency the user (or the API caller) pays. Synchronous is the right tool when the business rule must be true before the operation is considered successful — a credit-limit veto, a required related-record invariant, a mutation of Target the core operation must see.
An asynchronous plugin is queued after the transaction commits. It cannot cancel the original write. It can fail on its own, retry, and be inspected in System Jobs. It is the right tool for outbound notifications, expensive fan-out, and anything that would make the user's save feel like a batch job. Registering the credit-limit rule as asynchronous quietly turns a veto into a post-hoc cleanup, which is a different product with different failure modes.
The trap is to make every plugin synchronous "so it is reliable." Reliability and veto power are not the same thing. Synchronous Retrieve plugins, synchronous steps on high-volume messages, and synchronous work that calls external HTTP endpoints hold locks and threads the platform needs for everyone else. Prefer asynchronous for side effects; reserve synchronous for rules that must share a transaction with the core operation. The credit-limit plugin is the latter. Most telemetry, indexing, and integration plugins are the former.
One question at a time. A miss names the misconception — never the correct option.
These buttons simulate rubric updates the engine will own later. Mastery is per dimension; the gate does not average.
Exam mode revokes the coaching toolset — the agent cannot hint, coach, or reveal while the clock runs.