[eric] browser: a signed-in page is not a login wall just because it says sign in

This commit is contained in:
ciregenz
2026-07-31 13:03:58 -07:00
parent 0cf7d111c2
commit 2c63367ae0
2 changed files with 82 additions and 5 deletions
@@ -38,9 +38,13 @@ P_LOGIN_WALL_URL_RE = re.compile(
r"/(?:log[_-]?in|sign[_-]?in|signin|logon)(?:[/?#]|$)",
re.I,
)
# A password box disqualifies the page whoever is signed in: whatever that form is for, typing a
# post into it is wrong. Kept apart from the softer copy below because only this one is absolute.
P_PASSWORD_FIELD_RE = re.compile(r'<\s*textbox\s+"[^"]*(?:password|passwd)', re.I)
# Wording a login screen uses. Also, unfortunately, wording a signed-IN page uses in its footer and
# its upsells, which is why this half is overridable and the password field is not.
P_LOGIN_WALL_STATE_RE = re.compile(
r'<\s*textbox\s+"[^"]*(?:password|passwd)|(?:log|sign)\s?in to |'
r"continue with (?:google|apple|facebook)",
r"(?:log|sign)\s?in to |continue with (?:google|apple|facebook)",
re.I,
)
@@ -64,13 +68,37 @@ P_READONLY_RE = re.compile(
)
def login_wall_reason(current_url: str, state_text: str) -> str:
"""WHY this page reads as a login wall, or "" when it does not.
The bool alone sent a whole site to the model path with nothing to debug against: substack
declined as a wall on `https://substack.com/` while the account was demonstrably signed in, and
no amount of staring at the regexes reproduced it. A gate that can silently cost a site its
entire write path should be able to say which words convinced it."""
if current_url and P_LOGIN_WALL_URL_RE.search(current_url):
return f"url: {P_LOGIN_WALL_URL_RE.search(current_url).group(0)}"
if not state_text:
return ""
pw = P_PASSWORD_FIELD_RE.search(state_text)
if pw:
return f"password field: {pw.group(0)[:60]}"
soft = P_LOGIN_WALL_STATE_RE.search(state_text)
if not soft:
return ""
# "Sign in to ..." and "Continue with Google" are what a login screen says, and ALSO what a
# signed-in page's footer, upsell and embedded-content strip say. Treating them as proof cost
# substack its whole write path. The veto looks_signed_out already trusts settles it: a control
# that is meaningless unless you are authenticated outranks marketing copy.
if P_SIGNED_IN_RE.search(state_text):
return ""
return f"copy: {soft.group(0)[:60]}"
def looks_like_login_wall(current_url: str, state_text: str) -> bool:
"""A login/auth page (by URL) or an auth form in the perception (a password field, a
'Log in to X' heading, an OAuth 'Continue with ...'). The scripted send declines here:
a real composer never shares a page with these, and filling here types a login field."""
if current_url and P_LOGIN_WALL_URL_RE.search(current_url):
return True
return bool(state_text and P_LOGIN_WALL_STATE_RE.search(state_text))
return bool(login_wall_reason(current_url, state_text))
# SOFT signed-out: the site serves a browsable page with no auth form and no login URL, it just
+49
View File
@@ -0,0 +1,49 @@
"""The login-wall gate: what it must catch, and what it must stop catching.
This gate exists because the reveal finder once filled an Instagram login form and armed the page's
own submit as a "send". It is load-bearing and it fails safe, so the temptation is to leave it broad.
Broad turned out to have its own cost. Measured live 2026-07-31, substack.com declined as an auth
wall while the account was demonstrably signed in, which takes an entire site out of the write path
for as long as nobody notices. Sites print "Sign in to ..." in footers, upsells and embedded content
strips, and that copy is not evidence of a wall on a page that is also showing you your own account
menu. So the copy half is overridable by a signed-in affordance and the password half is not.
"""
from backend.apps.agents.browser import browser_send_parse as sp
SIGNED_IN = ('[1]<button "Account menu">\n'
'[4]<link "Sign in to read more">\n'
'[7]<textbox "Write a note">')
def test_a_signed_in_page_is_not_a_wall_just_because_it_says_sign_in():
"""The substack shape: login copy sitting next to proof you are already logged in."""
assert not sp.looks_like_login_wall("https://substack.com/", SIGNED_IN)
def test_a_password_box_convicts_no_matter_who_is_signed_in():
"""The veto is COPY-only on purpose. Whatever a password form is for, a post does not go in it,
and 'but the user is logged in' is not a reason to start typing into one."""
assert sp.looks_like_login_wall(
"https://site.com/x", '[1]<button "Sign out">\n[3]<textbox "Password">')
def test_login_copy_still_convicts_with_nothing_to_weigh_against_it():
"""Without a signed-in affordance the copy is the only evidence there is, and it stands."""
assert sp.looks_like_login_wall("https://site.com/x", '[4]<link "Log in to X to continue">')
def test_login_urls_are_still_walls_outright():
"""Unchanged, and not overridable: a login URL is the page's own declaration of what it is."""
assert sp.looks_like_login_wall("https://x.com/i/flow/login", SIGNED_IN)
assert sp.looks_like_login_wall("https://accounts.google.com/v3/signin/identifier", SIGNED_IN)
def test_the_decline_names_its_own_trigger():
"""The bool alone left a whole site declining with nothing to debug against: no amount of
re-reading the regexes reproduced substack, because the reason was never written down."""
assert "url:" in sp.login_wall_reason("https://x.com/i/flow/login", "")
assert "password field:" in sp.login_wall_reason("https://site.com/x", '[3]<textbox "Password">')
assert "copy:" in sp.login_wall_reason("https://site.com/x", "Log in to X to continue")
assert sp.login_wall_reason("https://substack.com/", SIGNED_IN) == ""