sungwy commented on code in PR #13879:
URL: https://github.com/apache/iceberg/pull/13879#discussion_r3462026174


##########
open-api/rest-catalog-open-api.yaml:
##########
@@ -3632,6 +3641,301 @@ components:
           additionalProperties:
             type: string
 
+    ReadRestrictions:
+      type: object
+      description: >
+          Read restrictions for a table.
+
+          A reader evaluates the row filter against original, untransformed 
column
+          values, then applies required-column-projections to the surviving 
rows.
+          Each action must produce a value of the same type as the input 
column.
+          If a reader cannot apply any returned restriction (a filter 
expression
+          or an action), it must fail the query and must not silently return 
raw,
+          partial, or empty results.
+
+          If a projection targets a field, that action governs every value 
reachable
+          through it; other projections in the same object that target a 
descendant
+          of that field have no effect.
+
+          An empty ReadRestrictions object (no required-column-projections and 
no
+          required-row-filter) imposes no restrictions and is equivalent to the
+          field being absent from the response.
+      example:
+        required-column-projections:
+          - field-id: 4
+            action: show-last-4
+          - field-id: 6
+            action: replace-with-null
+          - field-id: 8
+            action: truncate-to-year
+          - field-id: 10
+            action: sha-256-global
+          - field-id: 12
+            action: mask-alphanum
+        required-row-filter:
+          type: eq
+          term: region
+          value: US
+      properties:
+        required-column-projections:
+          description: >
+            A list of columns that require specific actions to be applied when 
reading.
+            A server must not return an action for a column whose type is not 
listed in
+            that action's "Applicable to" set. If absent or empty, no required 
actions
+            apply; columns not listed are not subject to any required action.
+
+            1. For each column listed, the reader must apply the specified 
action before
+              returning values for that column.
+
+            2. The reader must replace all output references to the column 
with the result
+              of the action, presenting the result under the original column 
name. For
+              example, if the action for column 'cc' is mask-alphanum, the 
reader must
+              return the masked value as 'cc' in the query output.
+
+            3. A column must appear at most once in 
required-column-projections.
+          type: array
+          items:
+            $ref: '#/components/schemas/Action'
+        required-row-filter:
+          description: >
+            An expression that filters rows in the table that the 
authenticated principal does not have access to.
+
+            1. The expression must evaluate to a boolean (TRUE or FALSE; 
Iceberg expressions
+              never produce NULL). A reader must discard any row for which the 
filter
+              evaluates to FALSE, and no information derived from discarded 
rows may be
+              included in the query result.
+
+            2. If this property is absent, null, or always true then no 
mandatory filtering is required.
+          allOf:
+            - $ref: '#/components/schemas/Expression'
+
+    Action:
+      discriminator:
+        propertyName: action
+        mapping:
+          mask-alphanum: '#/components/schemas/MaskAlphanum'
+          mask-to-fixed-value: '#/components/schemas/MaskToFixedValue'
+          replace-with-null: '#/components/schemas/ReplaceWithNull'
+          show-first-4: '#/components/schemas/ShowFirst4'
+          show-last-4: '#/components/schemas/ShowLast4'
+          truncate-to-year: '#/components/schemas/TruncateToYear'
+          truncate-to-month: '#/components/schemas/TruncateToMonth'
+          sha-256-global: '#/components/schemas/Sha256Global'
+          sha-256-query-local: '#/components/schemas/Sha256QueryLocal'
+      type: object
+      required:
+        - action
+        - field-id
+      properties:
+        action:
+          type: string
+        field-id:
+          type: integer
+          description: Field ID of the column being projected.
+
+    MaskAlphanum:
+      description: >
+        Redacts the column value using the following rules to transform 
Unicode code points:
+
+        - Digits (U+0030–U+0039, 0-9) are replaced with 'n'
+        - The following punctuation characters are kept as-is:
+            U+0028 '('  LEFT PARENTHESIS
+            U+0029 ')'  RIGHT PARENTHESIS
+            U+002C ','  COMMA
+            U+002E '.'  FULL STOP
+            U+002D '-'  HYPHEN-MINUS
+            U+0040 '@'  COMMERCIAL AT
+        - All other Unicode characters (including letters, whitespace, and any 
punctuation
+          not listed above) are replaced with 'x'
+
+        For example: "[email protected]" -> "[email protected]"
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: string
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "mask-alphanum"
+
+    MaskToFixedValue:
+      description: >
+        Replaces the column value with a type-specific fixed value.
+        Readers must use exactly the values listed below to ensure consistency
+        across implementations.
+
+        Fixed values by type:
+        - boolean: false
+        - int: 0
+        - long: 0
+        - float: 0.0
+        - double: 0.0
+        - decimal(p, s): 0 (the unscaled value is 0)
+        - string: "XXXXXXXX"
+        - date: 1970-01-01
+        - time: 00:00:00
+        - timestamp: 1970-01-01T00:00:00
+        - timestamptz: 1970-01-01T00:00:00+00:00
+        - timestamp_ns: 1970-01-01T00:00:00.000000000
+        - timestamptz_ns: 1970-01-01T00:00:00.000000000+00:00
+        - uuid: 00000000-0000-0000-0000-000000000000
+        - fixed(n): n zero bytes
+        - binary: empty byte sequence
+        - variant: {}
+        - geometry: POINT EMPTY
+        - geography: POINT EMPTY
+        - list: empty list []
+        - map: empty map {}
+        - struct: struct with each field set to its type-specific default 
(applied recursively)
+
+        NULL input is also replaced with the type-specific fixed value; NULL 
is not preserved.
+
+        Applicable to: all data types
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "mask-to-fixed-value"
+
+    ReplaceWithNull:
+      description: >
+        Replaces the entire column value with NULL. NULL input is preserved 
(NULL -> NULL).
+        A server must not return this action for a required (non-nullable) 
column.
+
+        Applicable to: all optional types
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "replace-with-null"
+
+    ShowFirst4:
+      description: >
+        Preserves the first 4 Unicode code points of the column value and 
redacts the remainder
+        using mask-alphanum rules (see MaskAlphanum for the exact character 
rules).
+        Values with 4 or fewer Unicode code points are returned unchanged.
+
+        For example: "[email protected]" -> "[email protected]"
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: string
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "show-first-4"
+
+    ShowLast4:
+      description: >
+        Redacts all Unicode code points except the last 4 using mask-alphanum 
rules
+        (see MaskAlphanum for the exact character rules).
+        Values with 4 or fewer Unicode code points are returned unchanged.
+
+        For example: "4111-1111-1111-4444" -> "nnnn-nnnn-nnnn-4444"
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: string
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "show-last-4"
+
+    TruncateToYear:
+      description: >
+        Truncates the column value to year precision, setting month, day, and 
time components
+        to their minimum values. The output type matches the input type.
+
+        For example: 2024-07-15 -> 2024-01-01
+        For timestamptz and timestamptz_ns, truncation is performed in UTC.
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: date, timestamp, timestamptz, timestamp_ns, 
timestamptz_ns
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "truncate-to-year"
+
+    TruncateToMonth:
+      description: >
+        Truncates the column value to year and month precision, setting day 
and time components
+        to their minimum values. The output type matches the input type.
+
+        For example: 2024-07-15 -> 2024-07-01
+        For timestamptz and timestamptz_ns, truncation is performed in UTC.
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: date, timestamp, timestamptz, timestamp_ns, 
timestamptz_ns
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "truncate-to-month"
+
+    Sha256Global:
+      description: |
+        Applies SHA-256. Deterministic across all queries
+        and engines: the same input always produces the same output.

Review Comment:
   nit - we use the term `readers` in describing other masking actions, but we 
use `engines` here:
   ```suggestion
           and readers: the same input always produces the same output.
   ```



##########
open-api/rest-catalog-open-api.yaml:
##########
@@ -3632,6 +3641,301 @@ components:
           additionalProperties:
             type: string
 
+    ReadRestrictions:
+      type: object
+      description: >
+          Read restrictions for a table.
+
+          A reader evaluates the row filter against original, untransformed 
column
+          values, then applies required-column-projections to the surviving 
rows.
+          Each action must produce a value of the same type as the input 
column.
+          If a reader cannot apply any returned restriction (a filter 
expression
+          or an action), it must fail the query and must not silently return 
raw,
+          partial, or empty results.
+
+          If a projection targets a field, that action governs every value 
reachable
+          through it; other projections in the same object that target a 
descendant
+          of that field have no effect.
+
+          An empty ReadRestrictions object (no required-column-projections and 
no
+          required-row-filter) imposes no restrictions and is equivalent to the
+          field being absent from the response.
+      example:
+        required-column-projections:
+          - field-id: 4
+            action: show-last-4
+          - field-id: 6
+            action: replace-with-null
+          - field-id: 8
+            action: truncate-to-year
+          - field-id: 10
+            action: sha-256-global
+          - field-id: 12
+            action: mask-alphanum
+        required-row-filter:
+          type: eq
+          term: region
+          value: US
+      properties:
+        required-column-projections:
+          description: >
+            A list of columns that require specific actions to be applied when 
reading.
+            A server must not return an action for a column whose type is not 
listed in
+            that action's "Applicable to" set. If absent or empty, no required 
actions
+            apply; columns not listed are not subject to any required action.
+
+            1. For each column listed, the reader must apply the specified 
action before
+              returning values for that column.
+
+            2. The reader must replace all output references to the column 
with the result
+              of the action, presenting the result under the original column 
name. For
+              example, if the action for column 'cc' is mask-alphanum, the 
reader must
+              return the masked value as 'cc' in the query output.
+
+            3. A column must appear at most once in 
required-column-projections.
+          type: array
+          items:
+            $ref: '#/components/schemas/Action'
+        required-row-filter:
+          description: >
+            An expression that filters rows in the table that the 
authenticated principal does not have access to.
+
+            1. The expression must evaluate to a boolean (TRUE or FALSE; 
Iceberg expressions
+              never produce NULL). A reader must discard any row for which the 
filter
+              evaluates to FALSE, and no information derived from discarded 
rows may be
+              included in the query result.
+
+            2. If this property is absent, null, or always true then no 
mandatory filtering is required.
+          allOf:
+            - $ref: '#/components/schemas/Expression'
+
+    Action:
+      discriminator:
+        propertyName: action
+        mapping:
+          mask-alphanum: '#/components/schemas/MaskAlphanum'
+          mask-to-fixed-value: '#/components/schemas/MaskToFixedValue'
+          replace-with-null: '#/components/schemas/ReplaceWithNull'
+          show-first-4: '#/components/schemas/ShowFirst4'
+          show-last-4: '#/components/schemas/ShowLast4'
+          truncate-to-year: '#/components/schemas/TruncateToYear'
+          truncate-to-month: '#/components/schemas/TruncateToMonth'
+          sha-256-global: '#/components/schemas/Sha256Global'
+          sha-256-query-local: '#/components/schemas/Sha256QueryLocal'
+      type: object
+      required:
+        - action
+        - field-id
+      properties:
+        action:
+          type: string
+        field-id:
+          type: integer
+          description: Field ID of the column being projected.
+
+    MaskAlphanum:
+      description: >
+        Redacts the column value using the following rules to transform 
Unicode code points:
+
+        - Digits (U+0030–U+0039, 0-9) are replaced with 'n'
+        - The following punctuation characters are kept as-is:
+            U+0028 '('  LEFT PARENTHESIS
+            U+0029 ')'  RIGHT PARENTHESIS
+            U+002C ','  COMMA
+            U+002E '.'  FULL STOP
+            U+002D '-'  HYPHEN-MINUS
+            U+0040 '@'  COMMERCIAL AT
+        - All other Unicode characters (including letters, whitespace, and any 
punctuation
+          not listed above) are replaced with 'x'
+
+        For example: "[email protected]" -> "[email protected]"
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: string
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "mask-alphanum"
+
+    MaskToFixedValue:
+      description: >
+        Replaces the column value with a type-specific fixed value.
+        Readers must use exactly the values listed below to ensure consistency
+        across implementations.
+
+        Fixed values by type:
+        - boolean: false
+        - int: 0
+        - long: 0
+        - float: 0.0
+        - double: 0.0
+        - decimal(p, s): 0 (the unscaled value is 0)
+        - string: "XXXXXXXX"
+        - date: 1970-01-01
+        - time: 00:00:00
+        - timestamp: 1970-01-01T00:00:00
+        - timestamptz: 1970-01-01T00:00:00+00:00
+        - timestamp_ns: 1970-01-01T00:00:00.000000000
+        - timestamptz_ns: 1970-01-01T00:00:00.000000000+00:00
+        - uuid: 00000000-0000-0000-0000-000000000000
+        - fixed(n): n zero bytes
+        - binary: empty byte sequence
+        - variant: {}
+        - geometry: POINT EMPTY
+        - geography: POINT EMPTY
+        - list: empty list []
+        - map: empty map {}
+        - struct: struct with each field set to its type-specific default 
(applied recursively)
+
+        NULL input is also replaced with the type-specific fixed value; NULL 
is not preserved.
+
+        Applicable to: all data types
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "mask-to-fixed-value"
+
+    ReplaceWithNull:
+      description: >
+        Replaces the entire column value with NULL. NULL input is preserved 
(NULL -> NULL).
+        A server must not return this action for a required (non-nullable) 
column.
+
+        Applicable to: all optional types
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "replace-with-null"
+
+    ShowFirst4:
+      description: >
+        Preserves the first 4 Unicode code points of the column value and 
redacts the remainder
+        using mask-alphanum rules (see MaskAlphanum for the exact character 
rules).
+        Values with 4 or fewer Unicode code points are returned unchanged.
+
+        For example: "[email protected]" -> "[email protected]"
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: string
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "show-first-4"
+
+    ShowLast4:
+      description: >
+        Redacts all Unicode code points except the last 4 using mask-alphanum 
rules
+        (see MaskAlphanum for the exact character rules).
+        Values with 4 or fewer Unicode code points are returned unchanged.
+
+        For example: "4111-1111-1111-4444" -> "nnnn-nnnn-nnnn-4444"
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: string
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "show-last-4"
+
+    TruncateToYear:
+      description: >
+        Truncates the column value to year precision, setting month, day, and 
time components
+        to their minimum values. The output type matches the input type.
+
+        For example: 2024-07-15 -> 2024-01-01
+        For timestamptz and timestamptz_ns, truncation is performed in UTC.
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: date, timestamp, timestamptz, timestamp_ns, 
timestamptz_ns
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "truncate-to-year"
+
+    TruncateToMonth:
+      description: >
+        Truncates the column value to year and month precision, setting day 
and time components
+        to their minimum values. The output type matches the input type.
+
+        For example: 2024-07-15 -> 2024-07-01
+        For timestamptz and timestamptz_ns, truncation is performed in UTC.
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: date, timestamp, timestamptz, timestamp_ns, 
timestamptz_ns
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "truncate-to-month"
+
+    Sha256Global:
+      description: |
+        Applies SHA-256. Deterministic across all queries
+        and engines: the same input always produces the same output.
+
+        Input-to-bytes encoding by type:
+        - string: UTF-8 encoded bytes
+        - int: 4 bytes, little-endian
+        - long: 8 bytes, little-endian
+        - binary: raw bytes as-is
+
+        Output encoding by type:
+        - string: 64-character lowercase hexadecimal string
+        - int: first 4 bytes of the digest, read as a little-endian int
+        - long: first 8 bytes of the digest, read as a little-endian long
+        - binary: the full 32-byte raw SHA-256 digest
+
+        NULL input is preserved (NULL -> NULL).
+
+        Applicable to: string, int, long, binary
+      allOf:
+        - $ref: '#/components/schemas/Action'
+      properties:
+        action:
+          type: string
+          const: "sha-256-global"
+
+    Sha256QueryLocal:
+      description: |
+        Applies SHA-256 with a per-query random salt, making the output 
non-deterministic
+        across queries while remaining consistent within a single query. The 
definition
+        of a query is left to the implementation.
+
+        The engine must generate a cryptographically random salt of at least 
16 bytes for each query.
+
+        For each column value, the engine must encode the value to bytes using
+        sha-256-global's input rules, prepend the per-query salt, and compute

Review Comment:
   nit, similar as above:
   ```suggestion
           The reader must generate a cryptographically random salt of at least 
16 bytes for each query.
   
           For each column value, the reader must encode the value to bytes 
using
           sha-256-global's input rules, prepend the per-query salt, and compute
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to