Hacker DirectoryHacker Directory

WEB / WEB-17.S02

GraphQL, streaming and message authorization

Separate current permission for each operation, field and event from its connection.

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mechanism

Read every scenario without motion

Title allowed

  1. Read message ready

    The consumer prepares a GraphQL read selecting notes.read, note-A and title. The API’s Duru/tenant-A context is already declared in this example; current permission for this message is not decided yet.

    Consumer
    notes.read message ready; title absent
    API / policy
    Policy waiting; title absent
    Public note store
    note-A unchanged; no read
  2. Message received

    The API records completed message arrival; connection admission does not settle field or time gates.

    Consumer
    notes.read message ready; title absent
    API / policy
    notes.read arrived; current gate pending
    Public note store
    note-A unchanged; no read
  3. Current gate allow

    Object, field, cost and current context conditions were separately accepted; the store read can now be prepared.

    Consumer
    notes.read message ready; title absent
    API / policy
    Object/field/current allow; store read ready
    Public note store
    note-A unchanged; no read
  4. Read reached store

    The store sees the approved read arrive completely; the title projection has not yet been read locally.

    Consumer
    notes.read message ready; title absent
    API / policy
    Object/field/current allow; store read ready
    Public note store
    Approved note-A read received; body pending
  5. Title projection

    A local read-only store operation prepares Tea & Bread; the note object is not mutated.

    Consumer
    notes.read message ready; title absent
    API / policy
    Object/field/current allow; store read ready
    Public note store
    Tea & Bread title body ready; mutation=false
  6. Title arrived at API

    The title body reached the API from the store; the API selects its response projection in the next local step.

    Consumer
    notes.read message ready; title absent
    API / policy
    Title received; API projection pending
    Public note store
    Tea & Bread title body ready; mutation=false
  7. Response ready

    The selected GraphQL projection contains the title; this fixture tests no actual parser or HTTP status.

    Consumer
    notes.read message ready; title absent
    API / policy
    GraphQL title response ready; no mutation
    Public note store
    Tea & Bread title body ready; mutation=false
  8. Title delivered

    The consumer receives the title at completed response arrival; only the permitted read projection is carried.

    Consumer
    Received title=Tea & Bread; mutation=false
    API / policy
    GraphQL title response ready; no mutation
    Public note store
    Tea & Bread title body ready; mutation=false

Field denied

  1. Read message ready

    The consumer prepares a GraphQL read selecting notes.read, note-A and title. The API’s Duru/tenant-A context is already declared in this example; current permission for this message is not decided yet.

    Consumer
    notes.read message ready; title absent
    API / policy
    Policy waiting; title absent
    Public note store
    note-A unchanged; no read
  2. Message received

    The API records completed message arrival; connection admission does not settle field or time gates.

    Consumer
    notes.read message ready; title absent
    API / policy
    notes.read arrived; current gate pending
    Public note store
    note-A unchanged; no read
  3. Current context

    The API evaluates object and operation context locally; no read has been sent to the store.

    Consumer
    notes.read message ready; title absent
    API / policy
    Object/action known; field/time gate pending
    Public note store
    note-A unchanged; no read
  4. Permission denied

    Object, current context and cost conditions pass, but fieldAllowed=false. The protected nullable-title value is not read; title=null and an error at note/title can be prepared without any store read.

    Consumer
    notes.read message ready; title absent
    API / policy
    Nullable title field denied; value=null
    Public note store
    note-A unchanged; no read
  5. Denial response

    The API prepares a GraphQL envelope with data.note.title=null and errors containing path=[note,title]. expectedBody=null means no protected-title projection, not absence of the envelope or a particular HTTP status.

    Consumer
    notes.read message ready; title absent
    API / policy
    Denial response ready; protected title absent
    Public note store
    note-A unchanged; no read
  6. Denial received

    The consumer sees the denial response arrive; its diagnostic contains no protected title value.

    Consumer
    GraphQL null title + errors received
    API / policy
    Denial response ready; protected title absent
    Public note store
    note-A unchanged; no read
  7. Result interpreted

    The consumer interprets the result locally; a schema or open channel is not counted as permission.

    Consumer
    No title value; HTTP status separate
    API / policy
    Denial response ready; protected title absent
    Public note store
    note-A unchanged; no read

Message expired

  1. Read message ready

    The consumer prepares a WebSocket read selecting notes.read, note-A and title. The API’s Duru/tenant-A context is already declared in this example; current permission for this message is not decided yet.

    Consumer
    notes.read message ready; title absent
    API / policy
    Policy waiting; title absent
    Public note store
    note-A unchanged; no read
  2. Message received

    The API records completed message arrival; connection admission does not settle field or time gates.

    Consumer
    notes.read message ready; title absent
    API / policy
    notes.read arrived; current gate pending
    Public note store
    note-A unchanged; no read
  3. Current context

    The API evaluates object and operation context locally; no read has been sent to the store.

    Consumer
    notes.read message ready; title absent
    API / policy
    Object/action known; field/time gate pending
    Public note store
    note-A unchanged; no read
  4. Permission denied

    The WebSocket was admitted earlier, but at now=120 and validUntil=120 current=false. Equality is invalid in this application; the new message is denied without a store read or protected-title preparation.

    Consumer
    notes.read message ready; title absent
    API / policy
    now=validUntil; message permission expired
    Public note store
    note-A unchanged; no read
  5. Denial response

    The API prepares a safe denial response for the expired message with no title. This is a WebSocket-message decision, not a GraphQL null-plus-errors envelope or a connection-closure result.

    Consumer
    notes.read message ready; title absent
    API / policy
    Denial response ready; protected title absent
    Public note store
    note-A unchanged; no read
  6. Denial received

    The consumer sees the denial response arrive; its diagnostic contains no protected title value.

    Consumer
    Message denial received; no title
    API / policy
    Denial response ready; protected title absent
    Public note store
    note-A unchanged; no read
  7. Result interpreted

    The consumer interprets the result locally; a schema or open channel is not counted as permission.

    Consumer
    No new title; prior data not retracted
    API / policy
    Denial response ready; protected title absent
    Public note store
    note-A unchanged; no read

Event withheld

  1. Subscription context

    A previously admitted stream exists; this start makes no permission claim for its next event.

    Consumer
    Subscription previously admitted; no new title
    API / policy
    Previous admission; current permission pending
    Public note store
    note-A unchanged; no read
  2. Candidate event

    The server considers a new note event locally; no event has yet been delivered to the consumer.

    Consumer
    Subscription previously admitted; no new title
    API / policy
    New event candidate; projection absent
    Public note store
    note-A unchanged; no read
  3. Current policy deny

    For the new SSE event concerning note-A, subscriptionAllowed=false is declared. Earlier admission, event IDs and cursors do not change this denial; no title projection is prepared.

    Consumer
    Subscription previously admitted; no new title
    API / policy
    Revoked; protected title body absent
    Public note store
    note-A unchanged; no read
  4. Delivery withheld

    The new event is withheld at the server; client closure/reconnect and erasure of prior data are not modeled.

    Consumer
    Subscription previously admitted; no new title
    API / policy
    Event delivery=0; mutation=false; title absent
    Public note store
    note-A unchanged; no read

ACTORS · STATE · DATA FLOW

A resolver is a permission boundary

A GraphQL schema describes expressible fields and types; it does not decide whether Duru may read a property of a particular note. After parsing and validation, the resolver must evaluate the authenticated actor, object relationship, action and field policy in the same context. Atlas Notes models only reading the title of note-A. The selected title field is nullable: denial produces null and an error at the relevant response path, while permitted sibling fields can be evaluated separately. A Non-Null field could instead propagate null to an appropriate nullable parent. This is an explicit application authorization-error policy, not a universal access-control library or HTTP status requirement imposed by GraphQL. The presence of both data and errors does not mean the protected title was returned.

Cost, types and permission answer different questions

Even a permitted resolver can consume different resources as list size and nested selections grow. Query cost is therefore a separate admission decision; depth alone does not describe all fan-out. The ledger’s title weight of 1 and list limit of 10 are selected teaching values, not constants defined by GraphQL. Cost approval does not grant permission, and permission approval does not grant an unlimited work budget. Different node and relationship paths to the same object should apply the same policy. Where a cache or batch loader is used, its key and result projection must account for the relevant actor, tenant and field context. The scene runs no query parser, HTTP binding, actual resolver or cache. It exposes the conditions under which a permitted title projection may be prepared.

From WebSocket connection to message

Accepting a WebSocket handshake opens a communication channel. That decision does not automatically permit every future message or object. A browser Origin check helps evaluate a connection initiated by an expected web application; it is not independent identity proof for a non-browser client. Cookie attachment also depends on cookie and browser rules. The message handler interprets an expected shape and action, then applies current actor/session state and object policy. In the expired branch the channel was previously accepted, but a new notes.read message is denied at now=120 and validUntil=120. Equality is invalid in this selected application profile; the WebSocket protocol does not define that session timer. No read reaches the store and no title body is prepared.

The lifetime of an SSE subscription

SSE normally streams events from server to client; EventSource is not a bidirectional command channel. Besides initial subscription admission, future events need the correct recipient and object scope. An event ID or reconnect cursor describes where to resume; it creates neither actor identity nor fresh permission. A revoked subscription withholds the next title event. This scene branch ends at the server’s local gate: client observation of closure, reconnection and withdrawal of previously received data are not simulated. EventSource can attempt to reconnect after a connection closes, so the server must evaluate fresh admission using current context. A retry interval assists transport behavior; it guarantees neither exactly-once business delivery nor lossless replay of every event. Transport progress and permission decisions remain separate states.

A precise introduction to gRPC and SOAP

gRPC expresses a service method call with typed inputs and outputs, commonly using Protocol Buffers by default. Unary, server streaming, client streaming and bidirectional streaming are different message flows. Ordering within an individual RPC is not permission for another RPC or a business action. Channel credentials and call credentials have different scopes; the application still decides method and object access. SOAP 1.2 describes an XML Envelope with an optional Header and a required Body. Processing a header at a particular node and directing the Body to the ultimate recipient do not prove that a notes.read operation is permitted. Security features belong to additional bindings/extensions and application profiles. The artifact is a typed comparison ledger only: no protobuf message, SOAP XML parser, WS-Security signature or remote RPC has run.

2. Red · Trust & Impact

Read every scenario without motion

Field denial

  1. Operation conditions were selected

    The GraphQL field-denied row has connectionAccepted=true, objectAllowed=true and fieldAllowed=false. An allowed object does not automatically expose title.

    Operation conditions
    GraphQL field gate
    Current policy gate
    Policy pending
    Resource projection
    Title not prepared
  2. The independent gate condition was separated

    Even with costAllowed=true and subscriptionAllowed=true, fieldAllowed remains false. Passing a cost budget does not grant field permission.

    Operation conditions
    Other gates=true
    Current policy gate
    Field=false
    Resource projection
    Resource delivery pending
  3. Operation-policy denial was established

    expectedAllowed=false, expectedResourceDelivery=false and expectedMutation=false. The handler does not prepare a protected title projection.

    Operation conditions
    Allowed=false
    Current policy gate
    Mutation=false
    Resource projection
    Protected body=null
  4. The response and protected data were separated

    With the selected nullable title, graphqlEnvelope has data.note.title=null and errors at note/title. A null protected body does not mean the whole envelope is absent.

    Operation conditions
    Permission deny known
    Current policy gate
    Null title + errors
    Resource projection
    Mutation=false
  5. Transport was not converted into policy

    A GraphQL HTTP status is not automatically derived from this envelope. Typed selection, cost limits and resource/property permission are separate contract layers.

    Operation conditions
    Channel ≠ operation grant
    Current policy gate
    Policy gate independent
    Resource projection
    No extra status claim
  6. Denial scope remained at the resource decision

    The known result is withheld title delivery and mutation. This shows the meaning of the nullable policy ledger, not execution of a GraphQL engine or HTTP adapter.

    Operation conditions
    No resource delivery
    Current policy gate
    No mutation
    Resource projection
    Runtime adapter unobserved

Context expired

  1. Operation conditions were selected

    The WebSocket expired row has connectionAccepted=true and validUntil=120. The profile selects now=120; an open channel does not extend context lifetime.

    Operation conditions
    now=120; validUntil=120
    Current policy gate
    Policy pending
    Resource projection
    Title not prepared
  2. The independent gate condition was separated

    Object, field, subscription and cost conditions are true but current=false. Other positive fields cannot make an expired context current.

    Operation conditions
    Other gates=true
    Current policy gate
    Current=false
    Resource projection
    Resource delivery pending
  3. Operation-policy denial was established

    expectedAllowed=false, expectedResourceDelivery=false and expectedMutation=false. The handler does not prepare a protected title projection.

    Operation conditions
    Allowed=false
    Current policy gate
    Mutation=false
    Resource projection
    Protected body=null
  4. The response and protected data were separated

    This row delivers no new resource body. It does not imply erasure of previously delivered browser data or automatic connection closure.

    Operation conditions
    Permission deny known
    Current policy gate
    No new delivery
    Resource projection
    Mutation=false
  5. Transport was not converted into policy

    WebSocket connection credentials do not satisfy current actor/action/object conditions for every new message. The same distinction remains an application-policy question for streamed gRPC messages.

    Operation conditions
    Channel ≠ operation grant
    Current policy gate
    Policy gate independent
    Resource projection
    No extra status claim
  6. Denial scope remained at the resource decision

    The known result is denial of a new read at the lifetime boundary. Actual stream backpressure, Origin/Cookie enforcement and revocation distribution require separate observations.

    Operation conditions
    No resource delivery
    Current policy gate
    No mutation
    Resource projection
    Runtime adapter unobserved

ASSUMPTION · BOUNDARY · CONTROL

Overreading an open channel

The assumption to examine is that accepting a connection permits all later messages from that actor. It becomes a control failure only if the application reduces current session, operation and object decisions to the boolean recorded at channel admission. The ledger deliberately permits connectionAccepted=true and messageAllowed=false at the same time: at expiry no new read reaches the store. An admitted SSE subscription and permission to deliver its next event are also separate. This perspective does not label an open channel a vulnerability by itself. It asks where the handler applies current policy and what data is prepared before that gate. Without evidence about revocation propagation, the outcome is not a claim that revocation works or fails; that dependency is recorded as unknown. Previously delivered titles are not assumed to disappear from client memory.

Jumping from schema success to business permission

The second assumption is that type validation and a reasonable query cost eliminate the need for resolver object and field policy. The consequence need not be a mutation: returning a title projection can also be a disclosure that requires permission. Although this note is a harmless public teaching object, its selected title gate is explicit. The field-denied branch may return a response skeleton and errors, but contains no protected title value. Here “no body” means no title projection, not the absence of every GraphQL response envelope. A typed gRPC request or a well-formed SOAP Envelope does not inherit that business decision either. Review the conjunction of fixed policy rows and retain separate evidence for operation, object, field and time conditions. Query execution, endpoint discovery and attempts to bypass permission are outside this example.

3. Blue · Secure development & defense

Read every scenario without motion

Event gate closed

  1. The SSE subscription row was read

    The revoked row has connectionAccepted=true and current=true. subscriptionAllowed=false is a separate policy condition denying a new event.

    Message/event evidence
    SSE connection accepted
    Policy context review
    Subscription allowed=false
    Delivery conclusion
    Delivery pending
  2. Event and stream lifetime were separated

    SSE carries events from server to client. An earlier accepted subscription or cursor cannot replace resource permission for a new event.

    Message/event evidence
    Direction: server → client
    Policy context review
    Cursor ≠ permission
    Delivery conclusion
    New event gate required
  3. The negative-delivery outcome was matched

    expectedAllowed=false, expectedResourceDelivery=false and expectedBody=null. The expected absence is no new title event reaching the client.

    Message/event evidence
    Allowed=false
    Policy context review
    Resource delivery=false
    Delivery conclusion
    Body=null
  4. Historical data was not assumed erased

    This denial does not establish erasure of a previously delivered title. A new-delivery boundary and historical client-data lifetime are different questions.

    Message/event evidence
    New event withheld
    Policy context review
    Old delivery not retracted
    Delivery conclusion
    Mutation=false
  5. Revocation-propagation evidence was requested

    The row supplies subscriptionAllowed=false as a precondition. Observing when it reaches every subscriber requires adapter and policy-revision evidence.

    Message/event evidence
    Declared revocation known
    Policy context review
    Propagation evidence missing
    Delivery conclusion
    Distributed result UNKNOWN
  6. The event result was not copied to another protocol

    This SSE gate cannot prove that gRPC or SOAP automatically makes the same decision. SOAP Body actions and gRPC methods/messages need their own approved-handler policy binding.

    Message/event evidence
    SSE denial known
    Policy context review
    RPC/SOAP adapters separate
    Delivery conclusion
    No universal enforcement claim

Context missing

  1. The missing-context record was selected

    unknownEvidence has contextPresent=false and permission=null. This is not the same evidence state as known field denial or the expired row.

    Message/event evidence
    Context present=false
    Policy context review
    Permission=null
    Delivery conclusion
    Decision pending
  2. Uncomputed permission was preserved

    Permission remains unknown without subject, tenant, action and resource context. Using a channel alias as actor authority cannot fill the gap.

    Message/event evidence
    Policy inputs missing
    Policy context review
    Permission UNKNOWN
    Delivery conclusion
    No guessed actor
  3. The safe outcome was established separately

    expectedAllowed=false and expectedResourceDelivery=false are safe outcomes. Those booleans do not turn missing permission evidence into verified false.

    Message/event evidence
    Safe allow=false
    Policy context review
    Knowledge remains UNKNOWN
    Delivery conclusion
    Delivery=false
  4. Absence of body and mutation were retained together

    expectedBody=null and expectedMutation=false. Review checks withheld resource delivery and writes, not only an error message.

    Message/event evidence
    Body=null
    Policy context review
    Mutation=false
    Delivery conclusion
    Negative boundaries retained
  5. The cost budget was not treated as permission

    titleWeight=1 and listLimit=10 are cost choices for this profile. They are neither universal GraphQL constants nor replacements for missing identity.

    Message/event evidence
    Selected cost policy
    Policy context review
    Cost ≠ identity
    Delivery conclusion
    Context still missing
  6. The unknown cause was preserved for diagnosis

    Known denial and context loss need separate reasons. Safe withheld delivery does not establish correct policy operation until the missing trust source is identified.

    Message/event evidence
    No delivery known
    Policy context review
    Missing provenance unresolved
    Delivery conclusion
    No clean policy claim

IMPLEMENTATION · SECURITY CONTROL · VERIFICATION

One policy across different delivery forms

For the defensive design, readTitle is a decision over actor, tenant, note-A, action and property. A GraphQL resolver, WebSocket message handler, SSE event filter and gRPC method carry that decision into their own delivery format instead of leaving the only check at connection level. For SOAP, the parsed Body action is bound to an approved application handler. This need not become one global boolean: resource policy and field projection can remain separate, readable decisions. Cost and size limits form a budget independent of the permission gate. Document application-defined subscription expiry and revocation behavior rather than giving an open channel an unlimited identity lifetime. Cache keys and batch contexts preserve relevant policy inputs. Clients receive a safe, understandable failure while detailed decision reason, actor context and policy revision belong in access-controlled telemetry.

Check absence as well as successful results

The positive fixture checks that a permitted read produces the title projection. Negative fixtures additionally check store delivery=0, mutation=false and protectedBody=null. For GraphQL field denial, the selected null-plus-errors shape must agree with the nullable schema; an HTTP status is not automatically derived from it. A previously accepted WebSocket connection must not admit a new message at the time boundary, and a revoked SSE subscription must not deliver a new event to the client. Missing policy is different evidence from a known false decision: retain permissionUnknown and choose a safe deny outcome. That distinction helps explain whether failure came from a policy decision or lost context. The animation deterministically plays supplied ledger results. Actual browser Origin/cookie enforcement, stream backpressure, RPC servers and subscription adapters require separate integration evidence.

NOW APPLY IT TO THE CASE

Which gate stops new delivery even after connection, schema and budget pass?

GraphQL fields, WebSocket messages and SSE events need their own current policy conditions. Null protected bodies, nullable error envelopes and missing context are distinct outcomes.

Separate decisions for verified actor, tenant relation and requested action in the case. Do not substitute authentication or proof success for object permission.

Open the related case file ↗

READ THE EXAMPLE TOGETHER

Atlas Notes — decision ledger

Select a field and examine what it supports and where the evidence ends.

Read the raw artifact and field explanations
{
  "profile": {
    "noteId": "note-A",
    "title": "Tea & Bread",
    "actor": "Duru",
    "tenant": "tenant-A",
    "action": "notes.read",
    "field": "title",
    "now": 120,
    "selectedNullableTitle": true,
    "actualProtocols": false
  },
  "rows": [
    {
      "case": "normal",
      "channel": "graphql",
      "connectionAccepted": true,
      "contextPresent": true,
      "current": true,
      "objectAllowed": true,
      "fieldAllowed": true,
      "subscriptionAllowed": true,
      "costAllowed": true,
      "expectedAllowed": true,
      "expectedBody": {
        "title": "Tea & Bread"
      },
      "expectedResourceDelivery": true,
      "expectedMutation": false
    },
    {
      "case": "field-denied",
      "channel": "graphql",
      "connectionAccepted": true,
      "contextPresent": true,
      "current": true,
      "objectAllowed": true,
      "fieldAllowed": false,
      "subscriptionAllowed": true,
      "costAllowed": true,
      "expectedAllowed": false,
      "expectedBody": null,
      "expectedResourceDelivery": false,
      "expectedMutation": false,
      "graphqlEnvelope": {
        "data": {
          "note": {
            "title": null
          }
        },
        "errors": [
          {
            "message": "Field not permitted",
            "path": [
              "note",
              "title"
            ]
          }
        ]
      }
    },
    {
      "case": "expired",
      "channel": "websocket",
      "connectionAccepted": true,
      "contextPresent": true,
      "current": false,
      "validUntil": 120,
      "objectAllowed": true,
      "fieldAllowed": true,
      "subscriptionAllowed": true,
      "costAllowed": true,
      "expectedAllowed": false,
      "expectedBody": null,
      "expectedResourceDelivery": false,
      "expectedMutation": false
    },
    {
      "case": "revoked",
      "channel": "sse",
      "connectionAccepted": true,
      "contextPresent": true,
      "current": true,
      "objectAllowed": true,
      "fieldAllowed": true,
      "subscriptionAllowed": false,
      "costAllowed": true,
      "expectedAllowed": false,
      "expectedBody": null,
      "expectedResourceDelivery": false,
      "expectedMutation": false
    }
  ],
  "costPolicy": {
    "titleWeight": 1,
    "listLimit": 10,
    "specUniversalConstants": false
  },
  "protocolLedger": [
    {
      "protocol": "GraphQL",
      "unit": "operation/field",
      "permission": "object + field",
      "transportStatusDerived": false
    },
    {
      "protocol": "WebSocket",
      "unit": "application message",
      "permission": "current actor + action + object",
      "originIsNonBrowserIdentity": false
    },
    {
      "protocol": "SSE",
      "unit": "subscription/event",
      "direction": "server to client",
      "cursorIsPermission": false,
      "exactlyOnce": false
    },
    {
      "protocol": "gRPC",
      "unit": "service method and streamed message",
      "modes": [
        "unary",
        "server-streaming",
        "client-streaming",
        "bidirectional-streaming"
      ],
      "channelCredentialsAreMethodPermission": false
    },
    {
      "protocol": "SOAP 1.2",
      "unit": "Envelope / optional Header / required Body",
      "coreProvidesUniversalAuthz": false
    }
  ],
  "unknownEvidence": {
    "contextPresent": false,
    "permission": null,
    "expectedAllowed": false,
    "expectedBody": null,
    "expectedResourceDelivery": false,
    "expectedMutation": false
  },
  "boundaries": {
    "actualResolver": false,
    "actualOriginCookieEnforcement": false,
    "actualStream": false,
    "actualRPC": false,
    "actualSOAP": false
  }
}
rows
Channel admission and current permission conjunction; null denotes absence of the protected title.
protocolLedger
Protocol form compared with its business decision; not a wire capture.
unknownEvidence
Missing context is separate unknown evidence with a safe deny result.

Fixed public-note ledger; no actual query, socket, EventSource, protobuf or SOAP XML runs.

Two reality checks

A valid schema makes every field readable.

Schema validation and object/field authorization are separate decisions.

An open stream means permanent permission.

New messages/events need current context; a cursor is not permission.

YOUR TURN

Work through this story.

Predict the outcome, find the evidence boundary, and explain it in your own words.

The WebSocket connection has connectionAccepted=true, but now=validUntil=120 and current=false. Is the note body sent for the next message?

  1. No. expectedResourceDelivery=false.
  2. Yes. The initial handshake authorizes every later message forever.
Read the explained answer

No. expectedResourceDelivery=false. — An established connection does not renew expired authorization context. This message produces neither a resource body nor mutation.

The field-denied case has expectedBody=null, but the GraphQL envelope has data and errors. Does this mean the protected title was delivered?

Selected lesson artifact fields; teaching example

rows[1].fieldAllowed
false
rows[1].expectedBody
null
rows[1].graphqlEnvelope
{"data":{"note":{"title":null}},"errors":[{"message":"Field not permitted","path":["note","title"]}]}
  1. Yes. Any data field in the envelope means all titles were disclosed.
  2. No. Nullable title is null; errors reports the field denial.
Read the explained answer

No. Nullable title is null; errors reports the field denial. — Title is nullable in this schema. data.note.title=null is not the protected title value. Data+errors also does not establish a specific HTTP status.

A revoked SSE subscription stops events even with the connection open. Why is the same distinction needed for gRPC methods and streamed messages?

Read the explained answer

Channel establishment is no blanket permission for later events or messages. An SSE cursor provides continuation, not subscription permission or exactly-once. gRPC channel credentials do not replace service-method and streamed-message policy. GraphQL also needs field and cost conditions; these costs belong to this profile, not universal specification constants. Missing context withholds delivery; no real resolver, stream, RPC or SOAP runs.

□ I did not substitute channel admission for per-operation authorization.

□ I stated subscription/cursor and cost-policy scopes separately.

Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples

Sources and scope