Visitar URL original
feat: Implement RegistryServer.Proto RPC with RBAC-filtered response (#6558) by nquinn408 · Pull Request #6552 · feast-dev/feast · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
fix: Carry registry's real last_updated/version_id in RegistryServer.…
…Proto

Addresses review feedback on PR #6552: RegistryServer.Proto rebuilds the
RegistryProto from individual RBAC-filtered list calls and was stamping
last_updated with datetime.now(), making the registry look freshly committed on
every call. Copy the authentic last_updated and version_id from the source
registry proto instead, so cache consumers (e.g. the remote feature server) see
the registry's real freshness metadata. Only these two scalar fields are read
from the source proto — no objects — so RBAC filtering is unaffected.

Update the unit test to give the fake registry a proto() returning known
metadata and assert it is carried through (rather than asserting "now").

Signed-off-by: Nick Quinn <nicholas_quinn@apple.com>
  • Loading branch information
nickquinn408 committed Jun 28, 2026
commit b9daa9704144ad90268db110a34da6b6c6e892c6
9 changes: 8 additions & 1 deletion sdk/python/feast/registry_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,14 @@ def describable(resources: list) -> list:
):
registry_proto.permissions.append(permission.to_proto())

registry_proto.last_updated.FromDatetime(datetime.now(timezone.utc))
# Carry the registry's real last_updated/version_id rather than stamping "now":
# this proto is rebuilt from individual list calls (for RBAC filtering), but it must
# not look like a fresh commit on every call — clients such as the remote feature
# server key cache freshness off this metadata. Reading these two scalar fields from
# the source proto leaks nothing RBAC-protected (no objects are copied from it).
source_proto = self.proxied_registry.proto()
registry_proto.last_updated.CopyFrom(source_proto.last_updated)
registry_proto.version_id = source_proto.version_id
return registry_proto

def ApplyEntity(self, request: RegistryServer_pb2.ApplyEntityRequest, context):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
returned; with auth enabled only ``DESCRIBE``-permitted objects are included.
"""

from datetime import datetime, timezone
from unittest.mock import patch

from google.protobuf.empty_pb2 import Empty
Expand All @@ -14,9 +15,15 @@
from feast.entity import Entity
from feast.feast_object import FeastObject
from feast.project import Project
from feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto
from feast.registry_server import RegistryServer
from feast.value_type import ValueType

# The registry's authentic metadata, returned by _FakeRegistry.proto(). Proto() must carry these
# through rather than stamping "now" (issue #6558 review feedback).
_REGISTRY_LAST_UPDATED = datetime(2024, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
_REGISTRY_VERSION_ID = "test-version-id"


class _FakeRegistry:
"""Minimal BaseRegistry stand-in exposing only the list_* calls Proto uses."""
Expand All @@ -26,6 +33,14 @@ def __init__(self, projects, entities_by_project, data_sources_by_project):
self._entities = entities_by_project
self._data_sources = data_sources_by_project

def proto(self) -> RegistryProto:
# Source of the authentic last_updated / version_id metadata. Proto() reads only these
# scalar fields from here (no objects), so RBAC filtering is unaffected.
proto = RegistryProto()
proto.version_id = _REGISTRY_VERSION_ID
proto.last_updated.FromDatetime(_REGISTRY_LAST_UPDATED)
return proto

def list_projects(self, allow_cache: bool = False, tags=None):
return self._projects

Expand Down Expand Up @@ -80,8 +95,10 @@ def test_proto_returns_full_registry_when_no_auth():
assert {p.spec.name for p in result.projects} == {"proj_a", "proj_b"}
assert {e.spec.name for e in result.entities} == {"driver", "customer", "merchant"}
assert {d.name for d in result.data_sources} == {"src_a"}
# last_updated is stamped so cache consumers see a fresh timestamp.
assert result.HasField("last_updated")
# last_updated / version_id are carried from the registry's real proto (not stamped "now"),
# so cache consumers see the registry's authentic freshness metadata.
assert result.version_id == _REGISTRY_VERSION_ID
assert result.last_updated.ToDatetime(tzinfo=timezone.utc) == _REGISTRY_LAST_UPDATED


def test_proto_filters_by_describe_permission():
Expand Down
Loading