Skip to content

Releases: pyxle-dev/pyxle-plugins

pyxle-mail 0.1.0

15 Jun 05:44
ae5cb7a

Choose a tag to compare

First release. One mail.service over a swappable MailProvider contract.

Providers: console (default — logs, sends nothing), SMTP (stdlib, no extra deps), Resend (pyxle-mail[resend] extra).
MailService.send(...) with sender defaults, EmailMessage/SendResult models, fail-loud config validation, get_mail_service() shortcut.

Install: pip install pyxle-mail (with Resend: pip install pyxle-mail[resend])

pyxle-db 0.2.0

12 Jun 08:20
e6cc4b6

Choose a tag to compare

Changed (BREAKING)

  • Database.transaction() now yields a transaction whose methods are
    coroutines: await tx.execute(...), await tx.fetchone(...), etc.
    In 0.1 these calls were synchronous inside the async context manager.
  • Database.close() and Database.sync_transaction() are SQLite-only
    and raise UnsupportedOperationError on server backends. Use
    await db.aclose() and async with db.transaction() — both work on
    every backend.
  • Mapping (named) parameters are SQLite-only; portable SQL uses
    positional ? parameters.

Added

  • PostgreSQL backend via asyncpg (pip install 'pyxle-db[postgres]')
    and MySQL backend via asyncmy (pip install 'pyxle-db[mysql]').
    The base install remains SQLite-only with zero extra dependencies.

  • Database URLs: Database(...)/connect(...) accept
    sqlite:///..., postgresql://..., and mysql://... connection
    strings alongside the 0.1 bare SQLite path. DatabaseConfig and
    parse_database_url are exported for programmatic use.

  • Portable placeholders: qmark (?) SQL is translated per backend
    ($1 for PostgreSQL, %s for MySQL) with a literal-aware rewriter;
    ?? escapes a literal question mark for PostgreSQL JSON operators.

  • Backend-neutral Row result type (index + name access) and Dialect
    metadata, both exported from pyxle_db.

  • New error types: OperationalError (retryable connection/timeout
    family), ConfigurationError, and UnsupportedOperationError.
    Driver exceptions are translated on every backend — application code
    never handles sqlite3/asyncpg/asyncmy exceptions.

  • Datetimes come back timezone-aware UTC on every backend; naive values
    stored in the database are assumed UTC and tagged.

  • Plugin: new url setting that takes precedence over path, with
    env:VAR_NAME indirection so credentials stay out of the committed
    pyxle.config.json (startup raises ConfigurationError when the
    variable is unset). The plugin now also registers db.url, a
    password-redacted connection string for logging.

  • Migrations: backend-specific override files
    (0003-fulltext-index.postgresql.sql next to
    0003-fulltext-index.sql) for migrations that need per-dialect DDL.

  • DatabaseLike / TransactionLike protocols (pyxle_db.contract,
    exported at top level): the structural contract third-party database
    layers implement to back plugins like pyxle-auth. Database is the
    reference implementation; both protocols are runtime_checkable and
    the conformance is regression-tested.

Fixed

  • Plugin shutdown awaits Database.aclose(), releasing async pools
    cleanly instead of relying on the SQLite-only synchronous close.
  • Aware datetimes now bind on every backend (found by the live-server
    suites). PostgreSQL and MySQL pass parameters through
    utc_naive_params(): an aware datetime is converted to UTC and bound
    naive, matching the SQLite adapter and the read-side "naive equals
    UTC" rule. Previously asyncpg rejected aware datetimes for TIMESTAMP
    columns and asyncmy silently serialised the foreign wall clock.
  • The MySQL pool pins each session to UTC (SET time_zone = '+00:00'),
    so TIMESTAMP columns and NOW() are no longer shifted through the
    server's system time zone on read.
  • The mysql extra now includes cryptography: MySQL 8's default
    caching_sha2_password auth fails at connect without it.
  • Dependency floor corrected to pyxle-framework>=0.4.0 — the
    pyxle.plugins API first shipped in 0.4.0, so older resolutions
    could not import.

Install: pip install pyxle-db · extras: [postgres], [mysql]
Docs: https://pyxle.dev/docs/plugins/pyxle-db

pyxle-auth 0.2.0

12 Jun 08:21
e6cc4b6

Choose a tag to compare

Changed (BREAKING)

  • Requires pyxle-db>=0.2.0. Its transaction methods became
    coroutines (await tx.execute(...)), and all pyxle-auth SQL is now
    written in portable qmark style — the plugin works unchanged on
    SQLite, PostgreSQL, and MySQL (DML fully portable; shipped DDL targets
    SQLite/PostgreSQL — MySQL schema needs a dialect override, see README).
    Upgraders from 0.1: the ratelimit_buckets.key column is now
    bucket_key (KEY is reserved in MySQL); drop the old table — bucket
    data is ephemeral hourly counters and recreates itself.
  • The plugin now hard-requires the pyxle-db plugin to have run
    first. List "pyxle-db" before "pyxle-auth" in
    pyxle.config.json::plugins; startup aborts with an actionable
    error otherwise.
  • The ensureSchema plugin setting is removed. The plugin always
    applies its bundled migrations and then runs each service's
    idempotent ensure_schema() — both are no-ops on an up-to-date
    database, so there is nothing left to opt out of.

Added

  • Password reset and email verification flows, powered by
    TokenService: single-use, purpose-scoped, expiring tokens with
    only the SHA-256 stored at rest. The library never sends email —
    your app delivers the token through its own mailer.
  • RoleService (RBAC): roles, permissions, and per-user grants,
    registered as auth.rbac.
  • ApiTokenService: long-lived pyxle_pat_ personal access tokens
    with scopes, per-user caps enforced atomically, and revocation.
    Registered as auth.api_tokens.
  • Request guards: current_user, require_user_page,
    require_user_action, require_permission_page,
    require_permission_action, and bearer_token, re-exported from
    the package root.
  • New settings: password_reset_ttl_seconds (default 1800),
    email_verify_ttl_seconds (default 86400), and
    rate_limit_password_reset_per_hour (default 3), each with a
    PYXLE_AUTH_* environment variable and a camelCase plugin key.
  • Settings precedence: plugin settings in pyxle.config.json
    override PYXLE_AUTH_* environment variables, which override the
    built-in defaults. AuthSettings.from_env grew an overrides
    parameter to express this.
  • Bundled migrations (pyxle_auth/migrations) applied through
    pyxle_db.Migrator at startup, with ensure_schema() as
    belt-and-braces after.
  • New exports: SessionInfo, InvalidToken, TokenClaim,
    TokenService, ApiToken, ApiTokenService, TokenLimitReached,
    TOKEN_PREFIX, and RoleService.
  • Live-backend test suite (tests/test_live_backends.py) running the
    real plugin schema path and a full account lifecycle against
    PostgreSQL and MySQL (gated on PYXLE_DB_TEST_POSTGRES_URL /
    PYXLE_DB_TEST_MYSQL_URL, shared with pyxle-db's suites).
  • PYXLE_AUTH_STRICT environment variable: strict now resolves
    config > env > secure-default(True), so a committed config can stay
    production-safe (strict + Secure cookies) while local HTTP dev
    relaxes via the environment.
  • Bring your own database. Services and the plugin now bind to the
    pyxle_db.DatabaseLike protocol instead of the concrete Database
    class, and the plugin's requirement is the db.database service
    name — any plugin registering a protocol-satisfying object can back
    pyxle-auth (pyxle-db remains the reference provider and a hard
    dependency for the error types and migrator). The contract (surface,
    IntegrityError translation, dialect, datetimes) is documented in the
    README and enforced by tests/test_database_contract.py, which runs
    the full lifecycle against a deliberately foreign database object.

Fixed

  • Schema is now genuinely portable (found by the live-server
    suites). Key and indexed columns are VARCHAR(n) instead of TEXT
    (MySQL cannot index bare TEXT), a 0001-pyxle-auth-core.mysql.sql
    override uses DATETIME(6) (MySQL TIMESTAMP is 2038-capped,
    second-rounded, and session-time-zone converted), and
    ensure_schema() creates indexes through an information_schema
    probe on MySQL, which has no CREATE INDEX IF NOT EXISTS.
  • Dependency floor corrected to pyxle-framework>=0.4.0 — the
    pyxle.plugins API first shipped in 0.4.0.

Install: pip install pyxle-auth
Docs: https://pyxle.dev/docs/plugins/pyxle-auth