Repository navigation
feat(masking): mask column values in the grid, exports, AI and MCP - #3978
Merged
Merged
Conversation
# Conflicts: # apple/TablePro/Views/Main/Extensions/MainContentCoordinator+ResultEditing.swift
Contributor
Author
|
The red macOS Tests check is not from this PR. CI passed in full on 3bf4dc5, the commit before the merge. I will merge |
datlechin
enabled auto-merge (squash)
November 1, 2026 09:09
datlechin
added a commit
that referenced
this pull request
Nov 2, 2026
Brings main's 43 commits, among them the Pro plan name (#3989), column masking (#3978) and the SSH host name hardening (GHSA-94m6-qx4g-cpwg). - LicenseTier, LicensePresentationTests, LicenseTierTests: stay deleted, since accounts replace license keys; the next commit renames the plan in AccountCodes instead. - ProFeature: keeps paidPlanRequirement; main changed only a comment on requiredTier, which this branch dropped. - TeamLibraryModels and its tests: stay deleted with /v1. The refused SSH host check main added to sanitized() now guards TeamLibraryChange.connection, and its test moves to TeamLibrarySyncTests. - MainEditorContentView: the Query Insights refresh main added reads FeatureAccess, not LicenseManager. - project.yml: the app links main's TableProInfluxDBCore and TableProQdrantCore; TableProAnalytics stays out. - Localizable.xcstrings: merged key by key; no key changed on both sides.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
table.columnorcolumnpattern (*and?wildcards, any case), or by declared type, and picks a mask: Full (••••), Last 4 Characters, Email (j•••@example.com), Stable Hash or NULL. The first matching rule wins.additionalFieldsundermaskingRules, so iCloud sync and the Team Catalog carry them with no new CloudKit field. A rule saved while a window is open masks the rows it already shows, in every tab and result set; a removed rule takes effect on the next run. A rule with a style or target from a newer release decodes as Full, so it never shows a value.ColumnMasks, masks every row. It is applied where values enter or leave the app:TableRows, the store behind the grid, query results, Row Details, Copy and Copy As, charts, Export Results, JSON mode and the assistant's results summary. Every write of fetched values (first page, reload, load more, a value loaded later) goes through it, and a masked cell takes no edit.MaskingExportDataSourcewraps the data source File > Export and the streaming query export hand to every format plugin, forstreamRowsand the plugin's ownexecute. A query export matches by column, since its export table is named after the file. Rows that arrive before a header are refused, not passed through. Export Results masks a large value it loads from the server.DatabaseAccessBridge.runStatementandrunScript, which every MCP tool, the AI chat tools, AppleScript and Shortcuts read through.browse_tablenames its table sotable.columnrules match by table there.table.columnrule matches by column name. This masks more, never less. A query that renames or computes the column (SELECT email AS e) is not caught; the docs say so, and a Type rule narrows it.MCP and AI: no scope, gate or tool is widened. Masked columns now come back masked from
browse_table,execute_query,execute_scriptandexport_data, and from the in-app assistant's query tool. Filters and sorts in a request still run on the stored values.Left open:
Docs: TableProApp/docs#154, to merge after this one.
Test plan
MaskingPolicyTests: pattern matching by table, column, wildcard and type; each mask; the stable hash; rule order; round trips throughadditionalFieldsand iCloud sync; unknown styles decode as Full.MaskingTableRowsTestsandMaskingGridTests: a fetched result lands masked throughapplyPhase1Result; reload, load more and a later loaded value stay masked; a rule added later masks loaded rows; Copy as JSON copies the mask; the grid is read-only; Reveal is refused without authentication, applies to its own tab only, and turns the masks off for that tab.MaskingExportTests: File > Export streams by table and by object come back masked, a query export ignores its file name, a plugin's own query is masked, rows before a header are refused, Export Results masks a value loaded from the server.MaskingBridgeTests: a statement, every result set of a script, and the JSON an MCP client receives hold no raw value; a named table narrows atable.columnrule.ConnectionFormEditsTestsandConnectionBundleExporterTests: the form saves and clears rules; a Team Catalog bundle carries them.xcodebuild build-for-testing -testPlan Unit CODE_SIGNING_ALLOWED=NOon Xcode 27.2. This Mac has no signing profile, so the hosted suites run in CI.Fixes #3615