@@ -361,3 +361,168 @@ def test_flag_off_materialize_is_unchanged(tmp_path):
361361 assert 'embeddings_table' not in manifest and 'embeddings' not in manifest
362362 assert manifest ['families' ][FAMILY ]['rows' ] == 2
363363 assert codec .decode_family ((tmp_path / 'off' / plain [0 ]['digest' ]/ (FAMILY + '.jsonl' )).read_bytes ())[1 ] == rows
364+
365+
366+ def test_daemon_queue_url_strips_only_libpq_tls_params ():
367+ """The exact production QUEUE_DATABASE_URL shape: import_worker login, verify-full
368+ and a pinned CA bundle. The daemon DSN drops only the libpq TLS parameters the
369+ Rust parser rejects and keeps the user, password, host, port and dbname."""
370+ from psycopg2 .extensions import parse_dsn
371+ # 44-char password, letters+digits only (the genpw alphabet, URL-safe with no encoding).
372+ password = ('aZ09' * 11 )
373+ dsn = ('postgresql://import_worker:%s@db.example.internal:5432/polis'
374+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem' % password )
375+ derived = imp ._daemon_queue_url (dsn )
376+ assert 'sslmode' not in derived and 'sslrootcert' not in derived
377+ # Every stripped parameter is gone; everything else is byte-for-byte unchanged.
378+ assert derived == 'postgresql://import_worker:%s@db.example.internal:5432/polis' % password
379+ parsed = parse_dsn (derived )
380+ assert parsed ['user' ] == 'import_worker' and parsed ['password' ] == password
381+ assert parsed ['host' ] == 'db.example.internal' and parsed ['port' ] == '5432'
382+ assert parsed ['dbname' ] == 'polis'
383+ assert 'sslmode' not in parsed and 'sslrootcert' not in parsed
384+
385+
386+ def test_daemon_queue_url_preserves_percent_encoding_and_other_params ():
387+ """A percent-encoded password byte and a non-TLS parameter tokio-postgres accepts
388+ survive unchanged; only the TLS keys are dropped."""
389+ from psycopg2 .extensions import parse_dsn
390+ dsn = ('postgresql://import_worker:p%40ss%2Fword@db.example.internal:5432/polis'
391+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem'
392+ '&application_name=import&connect_timeout=10' )
393+ derived = imp ._daemon_queue_url (dsn )
394+ assert derived == ('postgresql://import_worker:p%40ss%2Fword@db.example.internal:5432/polis'
395+ '?application_name=import&connect_timeout=10' )
396+ parsed = parse_dsn (derived )
397+ assert parsed ['password' ] == 'p@ss/word' # the percent-encoding round-trips
398+ assert parsed ['application_name' ] == 'import' and parsed ['connect_timeout' ] == '10'
399+
400+
401+ def test_daemon_queue_url_odd_password_in_url_form_is_byte_preserved ():
402+ """An odd password in URL form (percent-encoded quotes, spaces and reserved bytes)
403+ is kept byte for byte; only the TLS keys are dropped."""
404+ from psycopg2 .extensions import parse_dsn
405+ # Encodes the literal password: 'a b'@=&/
406+ encoded = "%27a%20b%27%40%3D%26%2F"
407+ dsn = ('postgresql://import_worker:%s@db.example.internal:5432/polis'
408+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem' % encoded )
409+ derived = imp ._daemon_queue_url (dsn )
410+ assert derived == 'postgresql://import_worker:%s@db.example.internal:5432/polis' % encoded
411+ # The userinfo bytes were never decoded or re-encoded; libpq recovers the original.
412+ assert parse_dsn (derived )['password' ] == "'a b'@=&/"
413+
414+
415+ def test_daemon_queue_url_recognizes_percent_encoded_tls_keys ():
416+ """tokio-postgres percent-decodes parameter names, so an encoded sslmode/sslrootcert
417+ key must be recognized and stripped, not passed through as an unknown name."""
418+ # ssl%6Dode -> sslmode ; sslroot%63ert -> sslrootcert
419+ dsn = ('postgresql://import_worker:pw@db.example.internal:5432/polis'
420+ '?ssl%6Dode=verify-full&sslroot%63ert=/ca/global-bundle.pem&application_name=import' )
421+ derived = imp ._daemon_queue_url (dsn )
422+ assert derived == ('postgresql://import_worker:pw@db.example.internal:5432/polis'
423+ '?application_name=import' )
424+
425+
426+ def test_daemon_queue_url_drops_duplicate_tls_params_keeps_tls_text_in_values ():
427+ """Repeated TLS keys are all removed; a non-TLS value that merely looks like a TLS
428+ parameter (even percent-encoded) is left untouched."""
429+ dsn = ('postgresql://import_worker:pw@db.example.internal:5432/polis'
430+ '?sslmode=verify-full&sslrootcert=/ca/a.pem&sslrootcert=/ca/b.pem'
431+ '&application_name=sslmode%3Dverify-full' )
432+ derived = imp ._daemon_queue_url (dsn )
433+ assert derived == ('postgresql://import_worker:pw@db.example.internal:5432/polis'
434+ '?application_name=sslmode%3Dverify-full' )
435+
436+
437+ def test_daemon_queue_url_preserves_sslnegotiation ():
438+ """sslnegotiation is accepted and applied by the pinned tokio-postgres parser, so it
439+ is preserved rather than stripped under the 'remove only what the daemon reproduces'
440+ contract."""
441+ dsn = ('postgresql://import_worker:pw@db.example.internal:5432/polis'
442+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem&sslnegotiation=direct' )
443+ derived = imp ._daemon_queue_url (dsn )
444+ assert derived == ('postgresql://import_worker:pw@db.example.internal:5432/polis'
445+ '?sslnegotiation=direct' )
446+
447+
448+ @pytest .mark .parametrize ('dsn' , [
449+ 'host=db.example.internal port=5432 user=import_worker dbname=polis sslmode=verify-full' ,
450+ "host=db.example.internal user=import_worker password='a b' sslmode=verify-full" ,
451+ 'user=import_worker dbname=polis sslmode = verify-full sslrootcert = /ca/global-bundle.pem' ,
452+ ])
453+ def test_daemon_queue_url_refuses_keyword_dsns (dsn ):
454+ """Keyword/value DSNs are refused, not rewritten: their grammar cannot be edited
455+ safely by token splitting, and production never uses them."""
456+ with pytest .raises (ValueError , match = 'postgresql' ):
457+ imp ._daemon_queue_url (dsn )
458+
459+
460+ @pytest .mark .parametrize ('param' , [
461+ 'sslcrl=/ca/revoked.pem' ,
462+ 'sslcrldir=/ca/crls' ,
463+ 'ssl_min_protocol_version=TLSv1.3' ,
464+ 'ssl_max_protocol_version=TLSv1.3' ,
465+ 'sslcert=/ca/client.pem' ,
466+ 'sslkey=/ca/client.key' ,
467+ 'sslpassword=secret' ,
468+ 'gssencmode=require' ,
469+ 'sslcompression=1' ,
470+ 'ssl_%6Din_protocol_version=TLSv1.3' , # encoded 'm' -> ssl_min_protocol_version
471+ ])
472+ def test_daemon_queue_url_refuses_unreproduced_tls_params (param ):
473+ """A TLS policy parameter the daemon does not reproduce is refused, never silently
474+ dropped (which would hand the daemon a weaker policy than the import requires)."""
475+ dsn = ('postgresql://import_worker:pw@db.example.internal:5432/polis'
476+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem&' + param )
477+ with pytest .raises (ValueError , match = 'does not reproduce' ):
478+ imp ._daemon_queue_url (dsn )
479+
480+
481+ @pytest .mark .parametrize ('raw' , ['\t ' , '\n ' , '\r ' , '#' ], ids = ['tab' , 'lf' , 'cr' , 'hash' ])
482+ def test_daemon_queue_url_refuses_raw_tab_newline_cr_and_hash_in_password (raw ):
483+ """urlsplit deletes a raw tab/newline/CR and treats a raw '#' as a fragment start,
484+ either of which would change the password libpq sees. Refuse the raw byte and make
485+ the caller percent-encode it."""
486+ dsn = ('postgresql://import_worker:a' + raw + 'b@db.example.internal:5432/polis'
487+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem' )
488+ with pytest .raises (ValueError , match = 'percent-encode' ):
489+ imp ._daemon_queue_url (dsn )
490+
491+
492+ def test_daemon_queue_url_refuses_raw_hash_that_would_hide_a_policy_param ():
493+ """A raw '#' in a query value would push the parameters after it into urlsplit's
494+ fragment, bypassing the TLS-policy refusal below. Refuse it."""
495+ dsn = ('postgresql://import_worker:pw@db.example.internal:5432/polis'
496+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem'
497+ '&application_name=a#b&ssl_min_protocol_version=TLSv1.3' )
498+ with pytest .raises (ValueError , match = 'percent-encode' ):
499+ imp ._daemon_queue_url (dsn )
500+
501+
502+ @pytest .mark .parametrize ('raw' , ['\t ' , '\n ' , '\r ' ], ids = ['tab' , 'lf' , 'cr' ])
503+ def test_daemon_queue_url_refuses_raw_whitespace_in_a_retained_value (raw ):
504+ """The same raw-byte refusal applies to a retained (non-TLS) query value, not only
505+ the password."""
506+ dsn = ('postgresql://import_worker:pw@db.example.internal:5432/polis'
507+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem'
508+ '&application_name=a' + raw + 'b' )
509+ with pytest .raises (ValueError , match = 'percent-encode' ):
510+ imp ._daemon_queue_url (dsn )
511+
512+
513+ def test_daemon_queue_url_preserves_percent_encoded_control_bytes ():
514+ """The percent-encoded counterparts (%09 tab, %0A LF, %0D CR, %23 '#') pass through
515+ untouched in both the password and a retained value, and libpq recovers the literal
516+ bytes."""
517+ from psycopg2 .extensions import parse_dsn
518+ pw = 'a%09b%0Ac%0Dd%23e' # tab, LF, CR, '#'
519+ appname = 'x%09y%23z'
520+ dsn = ('postgresql://import_worker:' + pw + '@db.example.internal:5432/polis'
521+ '?sslmode=verify-full&sslrootcert=/ca/global-bundle.pem'
522+ '&application_name=' + appname )
523+ derived = imp ._daemon_queue_url (dsn )
524+ assert derived == ('postgresql://import_worker:' + pw + '@db.example.internal:5432/polis'
525+ '?application_name=' + appname )
526+ parsed = parse_dsn (derived )
527+ assert parsed ['password' ] == 'a\t b\n c\r d#e'
528+ assert parsed ['application_name' ] == 'x\t y#z'
0 commit comments