Skip to content

Instance endpoints need an obj_owner and are bounded in size (#30) - #31

Merged
thorwhalen merged 3 commits into
masterfrom
fix/instance-endpoint-owner-and-size
Oct 13, 2026
Merged

thorwhalen merged 3 commits into
masterfrom
fix/instance-endpoint-owner-and-size

Conversation

@thorwhalen

@thorwhalen thorwhalen commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Closes #30. Mirrors #29 (class endpoints) for instance endpoints: a handler whose endpoint is an object, dispatched through attr_names.

Change

  • Owner. An instance endpoint is one object that every client shares. It now needs obj_owner:
    • either a (request) -> owner hook, which refuses requests it does not identify (401);
    • or the named opt-in obj_owner=shared_objects (anyone).
    • Without one, building the service raises a ValueError naming both options.
    • Module endpoints are unchanged: a module's functions are like plain function endpoints.
  • Size. max_obj_size (default DFLT_MAX_OBJ_SIZE) and obj_sizeof (default bounded_deep_sizeof) apply to the instance.
    • It is measured when the service is built: an object already over the limit is refused there, so the error comes immediately, not on the first request.
    • It is measured again after every dispatched call, failed ones included.
    • A pre-built instance cannot be dropped the way a class endpoint's object is. So the call that takes it over the limit gets a 400, and the object is kept.
    • Every later call is refused before it runs until the object is back under the limit.
    • Memory is therefore bounded by the limit plus what the calls already running allocate.
    • Data kept outside the process (files, a database) is not measured. The docstring says so.
  • The issue's two smaller items:
    • AuthorizationError now maps to 401, and its subclasses ForbiddenError and OverwritesNotAllowed to 403. Before, all three got 400. Bottle and aiohttp now share one status table (error_status).
    • aiohttp_handle_request now resets current_request.

Breaking default

This is the same decision as #28, extended to instance endpoints: the safe default plus a named opt-in. The fleet has two such handlers, both in addaix/raglab_app and both exposing writes to anyone; an issue is filed there. examples/object_dispatch.py now passes obj_owner=shared_objects, with a comment.

Gates

  • pytest --doctest-modules py2http: 136 passed.
  • priv test-dependents py2http --transitive: py2http and extrude pass.

Adversarial review

Two fresh Opus passes.

Pass 1: SHIP-WITH-FIXES. It found no way past the owner gate. Fixed:

Pass 2, on those fixes: SHIP-WITH-FIXES. Fixed:

  • A str passed as obj_shrinkers was split into letters, and unknown names were accepted. Both are now refused at build.
  • A stale clear could erase a newer over-limit flag. Measuring and flagging now happen under one lock.
  • Untraversed holders (MethodType.__func__, function __dict__ and defaults, static and class methods) are now followed.
  • Exotic objects (a mock, a __getattr__ raising KeyError) made the measurement raise. They are now measured plainly.
  • Documented: a shrinker that also adds defeats the bound.

Behaviour change for class endpoints: an object holding a bound method of another object is now charged that whole object, as holding the object itself already was. If that is not wanted, raise max_obj_size or pass an obj_sizeof.

🤖 Generated with Claude Code

thorwhalen added a commit that referenced this pull request Oct 13, 2026
…als/closures

- obj_shrinkers: names still callable while an instance endpoint is over its
  limit, so a client can bring it back under (one client could otherwise lock
  everyone out).
- bounded_deep_sizeof follows what bound methods, partials and closures hold.
- Document what is not measured and the per-call cost; fix the 401/403 comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thorwhalen added a commit that referenced this pull request Oct 13, 2026
…, guarded traversal

- obj_shrinkers: a str is refused, every name must be dispatched.
- Measuring and setting/clearing the over-limit flag happen under one lock.
- bounded_deep_sizeof follows MethodType.__func__, function attributes and
  defaults, static/class methods; an object whose attributes raise is measured
  plainly instead of failing the call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thorwhalen and others added 3 commits October 13, 2026 05:15
An instance endpoint (an object exposed through attr_names) is one object every
client shares. Like class endpoints (#29), it now needs obj_owner: a
(request) -> owner hook that refuses unidentified requests, or the named
opt-in obj_owner=shared_objects. Module endpoints are unchanged.

max_obj_size / obj_sizeof bound it: checked when the service is built and
after every call; once over, the object is kept and calls are refused until
it is back under.

AuthorizationError now maps to 401 (its subclasses ForbiddenError and
OverwritesNotAllowed to 403) in the Bottle and aiohttp error handlers, which
share one status table. The aiohttp handler resets current_request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…als/closures

- obj_shrinkers: names still callable while an instance endpoint is over its
  limit, so a client can bring it back under (one client could otherwise lock
  everyone out).
- bounded_deep_sizeof follows what bound methods, partials and closures hold.
- Document what is not measured and the per-call cost; fix the 401/403 comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, guarded traversal

- obj_shrinkers: a str is refused, every name must be dispatched.
- Measuring and setting/clearing the over-limit flag happen under one lock.
- bounded_deep_sizeof follows MethodType.__func__, function attributes and
  defaults, static/class methods; an object whose attributes raise is measured
  plainly instead of failing the call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@thorwhalen
thorwhalen force-pushed the fix/instance-endpoint-owner-and-size branch from 9eb671f to a184a15 Compare October 13, 2026 05:15
@thorwhalen
thorwhalen merged commit 73e0df8 into master Oct 13, 2026
6 checks passed
@thorwhalen
thorwhalen deleted the fix/instance-endpoint-owner-and-size branch October 13, 2026 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Instance endpoints (attr_names on an object) have no ownership or size bound

1 participant