Skip to content

v6.1.0-edge.6: CodeGen reproducibility, IsA subtype composition, and privilege-escalation guards

The seventh Edge build of the 6.1 line — 95 changesets across 306 packages, and unusually inward-looking. The dominant theme is CodeGen telling the truth about a database built only from what the repo ships: a run of fixes that each began as “this works on my dev database and fails on a fresh install,” which is the class of defect that reaches customers first and developers last. Alongside it, IS-A subtype composition becomes declarative — an entity can now describe how to resolve its own subtype in metadata rather than in registered runtime code — and a sustained pass over privilege escalation, SQL-fragment injection surfaces, and undrained fetch bodies.

Edge builds are prereleases. They publish under the edge dist-tag and never move latest.

  • Entity.SubtypeSelector — declarative IS-A subtype resolution. An entity can carry a dotted foreign-key dereference path ending at the column that names its target subtype entity (ProductID.ProductTypeID.OrderLineExtensionEntity). BaseEntity.ResolveSubtypeEntityName() reads it when no runtime EntitySubtypeResolver is registered, and offline tooling — Loom, CodeGen — can determine conditional IS-A children without executing application code. Prospective subtype resolution and sync composition axes land alongside it.
  • Conversation-scoped skill activation. AISkill.ActivationScope distinguishes a one-shot capability (Run) from a persona or mode that persists (Conversation). A skill activated in a run belonging to a conversation stays active for that conversation via an MJ: Conversation Skills row and is re-requested at the start of every later root run until ended — still subject to every availability gate on each run.
  • Authorization.Check as a remotable operation, with composite-filter evaluation, so authorization decisions are callable across the wire rather than only in-process.
  • Image, Color and JSON EntityField.ExtendedTypes, with PhotoURL / LogoURL rendering as linked thumbnails in the entity viewer.
  • Host-controllable whiteboard ToolRoster that gates the toolbar, keyboard shortcuts and context menu together, plus host ReadOnly support.
  • Form section indicators — an unsaved-edits dot and an invalid-field count on the form rail and panel headers, re-resolving automatically when field visibility changes.
  • Writable geo — a real write path, isolated parallel providers, and skipGeoCoding for callers that already have coordinates.
  • Open App server packages load in every MJ process, with per-process scoping, so a dynamic package behaves the same in MJAPI, the CLI and CodeGen.
  • Artifacts without a viewer plugin now get a file card and a working download instead of an empty frame.
  • BaseEntity.FieldIsDirty for per-field edited checks.
  • The installer defaults to pnpm, with an explicit npm override.
  • CodeGen is idempotent against database state. Two runs over an unchanged database produce zero diffs; a single new column touches only that entity’s artifacts. Field-categorisation decisions persist to metadata/entities/decisions/, so a clean-room build matches a warm one.
  • Fresh-database drift eliminated. A cluster of fixes for output that differed between a long-lived dev database and one built only from migrations — pending EntityField discovery scoped to includeSchemas, IdentityClaim metadata tail and relationship dedupe, and UTC default normalisation.
  • Recurring reconcilers no longer leak into versioned migrations. omitRecurringScriptsFromLog now defaults to true. CodeGen’s SQL log was capturing spDeleteUnneededEntityFields, which then replayed from an intermediate schema state on a fresh install and deleted EntityField rows the migrations had correctly created — surfacing much later as Msg 213 on every Save(). A CI gate now refuses a migration carrying that prune.
  • PostgreSQL counterparts for the full v6 backlog, bringing migrations/v6migrations-pg/v6 to complete parity.
  • ExtraFilter accepts IN (SELECT … FROM entity BaseView), so a subquery against a base view is expressible without dropping to custom SQL.
  • One provider per JSON graph in sync, so nested children share the parent transaction.
  • Deterministic save-call SQL variable suffixes on SQL Server, and nested savepoints moved onto GenericDatabaseProvider where both dialects can use them.
  • The AI-model research routine prompt is checked in, including the cost-status rule that has twice broken a sync push.
  • Privilege-escalation and role-elevation guards on MJ: Users, MJ: Roles and MJ: User Roles — a non-Owner administrator can no longer create or delete users, or modify privileged columns on a user row.
  • Security hardening across request surfaces: CORS defaults, an OAuth error open redirect, consent scope grants, CustomWhereClause gating, client SQL fragments screened for subqueries, the Conditional action, the artifact iframe, and Gmail header handling.
  • Six recurring undrained-fetch-body leaks closed, and RemoteBrowserActionResolver’s session maps bounded.
  • Generated Validate() overrides are no longer silently deleted. mj codegen --no-ai emitted every entity subclass as though it had no validators, removing 56 committed overrides rather than declining to add new ones — because the load of persisted GeneratedCode was reachable on only one code path, and then gated behind the AI feature flag even there. Reading approved generated code is a database read; it is no longer treated as an AI call.
  • EntityField INSERTs no longer carry a literal Sequence. A literal collides on UQ_EntityField_EntityID_Sequence on any database built only from migrations, and reports itself as an unrelated foreign-key error.
  • InstanceConnectionString collapsed every connection to one identity in the SQL Server provider.
  • RLS exemption honours the permission row’s Can* flags rather than exempting wholesale.
  • The polymorphic EntityID/RecordID soft-link path works, instead of assuming every record pointer holds a single bare key value.
  • Five form controls stopped latching their disabled state, and the related-grid reserves horizontal-scrollbar height.
  • Cognito OAuth endpoints resolve from the hosted-UI domain in the MCP server.
  • Agent-generated media is stored in configured file storage rather than inline.
  • Conversation diagnostic logging is opt-in instead of unconditional.
  • Open App CodeGen_Run SQL is written to the app’s own migrations/codegen, not the core repo’s.