This release is a pre-release and may not be stable for production use.
FedoRA
Security-first federated learning — and federated knowledge learning for LLM agents
Quick Start · Federated Knowledge · API Stability · Industry Launch · Proof Workflow · Production Readiness · Documentation · Comparison · Contributing · Security
Why FedoRA?
The bigger idea behind FedoRA is federated knowledge learning: agents, devices, and organizations should be able to share useful learned knowledge without sharing raw private data, full local memory, or unrestricted internal state.
Classic federated learning is one case of this idea: participants exchange model parameters. Agentic systems need a more general exchange unit: LoRA/task adapters, summarized memories, tool-use traces, evaluation results, fact bundles, policies, skills, and distilled examples.
Enterprise teams deploying federated learning hit a practical problem: security configuration is manual, error-prone, and disconnected from the threats the deployment actually faces. You pick an aggregator, bolt on differential privacy separately, tune filters, track trust, and assemble audit logs without one object that explains why those choices belong together.
FedoRA turns a knowledge-sharing objective into an executable, auditable plan. Declare what kind of knowledge can cross the boundary; FedoRA records the artifact type, composes the supporting privacy/trust controls, and produces the receipts needed to review, reproduce, and port the run.
- Knowledge artifacts for parameters, adapters, memories, skills, examples, traces, eval results, fact bundles, and policies
- Defense selection for Byzantine robustness, privacy, poisoning, backdoors, and anomalous clients
- Composable execution plans through the UFCG/FedoRA Plan representation
- Privacy and trust artifacts that explain the selected DP, clipping, trust, and audit settings
- Portable execution paths for local proof workflows, gRPC/WebSocket experiments, and Flower/FLARE adapters
- Evidence packs from plan hashes, receipts, audit logs, and compliance-oriented summaries
Packaging: install the single
fedora-flpackage — that's the whole library.fedora-fl-securityandfedora-fl-runtimeare thin persona facades that re-export fromfedora-fland depend on it; they give each audience a clean import namespace (import fedora_security/fedora_runtime), but the implementation is not split into independently installable layers. The[security]and[knowledge]extras pull the optional dependencies for each path. Split rationale: docs/REPO_SPLIT.md.
This checkout targets the corrected beta 2.1.0b2. Before publication, evaluate
the supplied candidate wheels using the external review packet.
Once that version is published, pin it explicitly with
pip install "fedora-fl==2.1.0b2"; extras go before the version pin, for example
pip install "fedora-fl[security,grpc]==2.1.0b2". Both persona facades use the
same version. The approved-data pilot, three independent external users, and
deployment/security review remain separate promotion gates.
As of 2.0, FedoRA federates more than parameters. The same security-first engine now merges typed knowledge artifacts — LoRA adapters, distillation logits, prototypes, and natural-language memories and skills for LLM agents — through one pluggable merge interface. Classic FedAvg is the special case (the merge operator for the tensor artifact kind). See Federated Knowledge.
Current maturity: the FL security/evidence layer is production-gated. The native gRPC path is available for review-ready deployments only when fedora verify-grpc-config --review-ready passes for the concrete run config. WebSocket, Flower, and FLARE paths must still be evaluated against the Backend Capability Matrix before deployment. The federated-knowledge layer (fedora.knowledge) is beta: usable and tested, with pluggable production seams (real embeddings, isolated skill execution), but not yet production-gated — see its rows in the capability matrix.
import fedora
# Declare your threat model
threat = fedora.ThreatModel(
byzantine_fraction=0.2, # Expect up to 20% malicious clients
privacy_level="strong", # DP with epsilon=0.5
model_poisoning=True, # Defend against gradient attacks
)
# FedoRA auto-configures defenses
history = fedora.simulate(
client_fn=my_client_fn,
num_clients=50,
num_rounds=10,
artifact="adapter",
threat_model=threat,
initial_parameters=initial_params,
)
# MultiKrum aggregation, gradient clipping, anomaly detection,
# differential privacy, trust scoring, and audit trail
# are all auto-configured and composable.
Federated Knowledge (new in 2.0)
Agents built on frozen, hosted models have no weights to federate — their only shared substrate is knowledge: distilled lessons, reusable skills, adapters, prototypes. FedoRA 2.0 federates that knowledge through the same security-first engine, so a fleet of agents can pool what they learn without pooling private data. Validation, provenance binding, and staged adoption reduce the risk of poisoned contributions; they do not guarantee semantic correctness or prevent all prompt injections.
pip install "fedora-fl[knowledge]" # production embeddings; falls back gracefully without
from hashlib import sha256
from fedora.knowledge import (
ArtifactKind, Contribution, MemoryEntry, artifact_to_memory,
federate, memory_to_artifact, sharing_policy_for,
)
def lesson(client, key, value):
policy = sharing_policy_for(
ArtifactKind.MEMORY,
attestations={
"redactor_id": "demo-redactor-v1",
"redaction_report_hash": "sha256:" + sha256(client.encode()).hexdigest(),
},
)
art = memory_to_artifact(
MemoryEntry(f"{key}: {value}", key=key, value=value),
client_id=client, policy=policy,
)
return Contribution([art], weight=1.0, client_id=client)
# Synthetic redacted lessons; IDs and trust are coordinator-owned in a real run.
result = federate([
lesson("agent-a", "db.pool", "raise max_connections under load"),
lesson("agent-b", "db.pool", "raise max_connections under load"),
lesson("attacker", "db.pool", "disable the connection limit"),
], artifact="memory", local_context={
"trust_scores": {"agent-a": 0.9, "agent-b": 0.9, "attacker": 0.0},
})
for art in result.accepted:
m = artifact_to_memory(art)
print(m.key, "->", m.value, f"(support {m.support})")
# db.pool -> raise max_connections under load (support 2)
The default high-level boundary rejects non-shareable/private artifacts, malformed payloads, and missing kind-specific sharing evidence before merge. The built-in attestation check validates evidence format; applications must verify real receipt or signature issuers for stronger assurance. Source identity and trust must come from the coordinator's authenticated session, and merged support is resolved from trusted state. See the runnable client integration.
For a complete application flow, run the offline support-agent reference app:
python -m fedora.reference_apps.support_agents --rounds 2 --output support-demo.json
The bundled fixture is synthetic and uses keyed lookup with zero model API calls. The pilot guide covers approved-data input, participant trust, adoption, expiry and checkpoint recovery. The comparison methodology defines isolated and shared-memory baselines; these are not vendor performance results.
The merge ladder. Every artifact kind is a merge operator under one
contract (is_robust / is_private / is_idempotent / is_commutative);
async rounds require the last two. Each merger also declares assumptions,
limitations, and a maturity level (L1 exact merge, L2 schema-aware merge,
up to L5 utility-optimized merge):
| Kind | Merge operator | What it federates |
|---|---|---|
tensor |
FedAvg · Krum · trimmed mean · DP | model parameters (classic FL) |
adapter |
delta-space TIES / DARE (rank-heterogeneous) | LoRA fine-tunes |
logits |
FedMD/FedDF consensus + robust trimmed mean | predictions across heterogeneous models |
prototype |
FedProto count-weighted average | per-class embedding anchors |
memory |
validate → trust-weighted vote → quarantine | natural-language lessons |
skill |
test-gated acceptance (pooled evals) | executable skills |
Extended agent-native artifact kinds:
| Kind | Merge operator | What it federates |
|---|---|---|
tool_trace |
schema-aware workflow merge (L2 when workflow metadata is present) |
successful tool-use traces |
eval_result |
run-deduped weighted/median/trimmed/trust-weighted metrics | benchmark evidence and failure summaries |
fact_bundle |
highest-confidence claim selection | structured facts with provenance |
policy |
deterministic union + conflict reporting (L2) |
guardrails and operating rules |
example |
exact distilled-example dedupe | synthetic or distilled demonstrations |
The robust mergers turn a $0.667$ undefended memory-poisoning attack into $0.000$
attack success in the reference experiment. See the wire-format spec,
the position paper, and the reproducible
benchmark (python benchmarks/knowledge_federation_benchmark.py).
What FedoRA Offers
| Capability | What users get |
|---|---|
| Knowledge Objective Planner | Start with a KnowledgeObjective or artifact=...; receive a plan for what knowledge can cross the boundary and how it is validated. |
| Secure Experiment Builder | Start with clients, data, and a ThreatModel; receive a runnable configuration with aggregator, DP, defenses, trust, and audit defaults selected together. |
| Threat Model Compiler | Convert business/security concerns into a recommended defense stack with rationale, parameters, and validation hooks. |
| FedoRA Plan | Represent FL rounds as a typed UFCG plan with policy constraints, plan hashing, backend decisions, and receipts. |
| Composable Security Stack | Combine robust aggregation, DP, explicit SecAgg modes, anomaly detection, trust scoring, and attack simulation without hand-wiring each path. |
| Portability Layer | Run proof workflows locally, experiment with gRPC/WebSocket, or lower compatible plans into Flower/FLARE paths when existing infrastructure matters. |
| Evidence Pack | Export audit and receipt artifacts that show what ran, why defenses were selected, and how privacy/trust state evolved. |
import fedora
threat = fedora.ThreatModel(
byzantine_fraction=0.2,
privacy_level="strong",
model_poisoning=True,
)
plan = fedora.plan(
fedora.KnowledgeObjective(
name="agent-adapter-sharing",
artifact="adapter",
num_clients=50,
num_rounds=10,
threat_model=threat,
),
receipts_path="receipts/run.jsonl",
)
print(plan.plan_id)
print(plan.explain())
plan.export("exec_plan.json")
Want an even shorter starting point? Use a built-in scenario:
import fedora
plan = fedora.scenario("healthcare", num_clients=12, num_rounds=20).plan()
print(plan.run_config["strategy"])
fedora plan --scenario healthcare --clients 12 --rounds 20 --output healthcare_plan.json
Run the local proof workflow and export an evidence bundle:
fedora proof --scenario byzantine-privacy --clients 20 --rounds 3 --output-dir fedora_proof
Competitive Position
| Framework | Best at | FedoRA's role beside it |
|---|---|---|
| Flower | Mature FL app/runtime architecture and broad ecosystem | Add threat-driven defense composition and auditable plans around Flower-compatible work. |
| NVIDIA FLARE | Production cross-silo deployment, provisioning, filters, and operational controls | Generate or validate security plans and evidence before lowering into FLARE-style deployments. |
| FedML | Broad MLOps and run-anywhere FL workflows | Stay focused on the security/compiler layer instead of duplicating full MLOps. |
| OpenFL | Institution-oriented plans, TLS/PKI workflows, and healthcare-style collaborations | Make the plan contract more threat-aware and receipt-driven. |
| FATE | Vertical FL, MPC/HE workflows, and large enterprise deployments | Avoid competing on vertical FL; focus on horizontal FL security composition and evidence. |
| TensorFlow Federated | Typed federated computation research in TensorFlow | Keep FedoRA Plan backend-agnostic and security-oriented. |
| PySyft | Data-owner governance and privacy-preserving remote data science | Keep FedoRA FL-specific while borrowing the idea that governance artifacts matter. |
Backend Maturity
FedoRA's backend support is intentionally explicit:
| Path | Current claim |
|---|---|
| Local simulation | Beta-supported proof workflow for planning, attacks, defenses, and evidence. |
| local-mp / Ray | Optional simulation backends when dependencies are installed. |
| gRPC / WebSocket | Experimental deployment paths for controlled evaluation. |
| Flower / FLARE adapters | Compatibility layers with feature-specific caveats, not full runtime parity. |
See Backend Capability Matrix before making deployment or security claims.
Quick Start
Installation
pip install fedora-fl
Your First Secure FL Experiment
import numpy as np
import fedora
# 1. Define your client
class MyClient(fedora.NumPyClient):
def fit(self, parameters, config):
# Your local training logic here
updated = [p + np.random.randn(*p.shape) * 0.01 for p in parameters]
return fedora.FitResult(
parameters=fedora.Parameters.from_ndarrays(updated),
num_examples=1000,
metrics={"loss": 0.5},
)
def evaluate(self, parameters, config):
return fedora.EvalResult(loss=0.3, num_examples=500)
# 2. Run a simulation
history = fedora.simulate(
client_fn=lambda cid: MyClient(),
num_clients=20,
num_rounds=5,
initial_parameters=fedora.Parameters.from_ndarrays([np.ones(100)]),
)
print(history.summary())
Add Security in One Line
# Declare threats — defenses are auto-configured
history = fedora.simulate(
client_fn=lambda cid: MyClient(),
num_clients=20,
num_rounds=5,
threat_model=fedora.ThreatModel(
byzantine_fraction=0.3, # 30% malicious clients
privacy_level="strong", # DP with epsilon=0.5
model_poisoning=True, # Expect gradient attacks
backdoor_attack=True, # Expect backdoor triggers
),
initial_parameters=fedora.Parameters.from_ndarrays([np.ones(100)]),
)
What this auto-configures:
- MultiKrum aggregation (tolerates up to 30% Byzantine clients)
- Differential privacy (epsilon=0.5, delta=1e-6, Gaussian mechanism)
- Gradient clipping (norm bound = 1.0)
- Anomaly detection (spectral + similarity filtering)
- Trust scoring (per-client reputation tracking)
- Audit trail (hash-linked events for tamper detection and review)
Key Features
1. Declarative Threat Model
Declare your security requirements, and FedoRA auto-selects and configures the right combination of defenses instead of forcing each component to be wired independently.
threat = fedora.ThreatModel(
byzantine_fraction=0.2,
privacy_level="strong",
model_poisoning=True,
)
rec = threat.recommend_defenses()
print(rec.aggregator) # "multikrum"
print(rec.dp_enabled) # True
print(rec.dp_epsilon) # 0.5
print(rec.trust_scoring) # True
print(rec.anomaly_detection) # True
print(rec.rationale) # Human-readable explanation
2. 14 Aggregation Strategies
From standard averaging to Byzantine-robust to adaptive optimizers:
| Category | Aggregators |
|---|---|
| Standard | FedAvg, FedProx, FedNova |
| Byzantine-Robust | TrimmedMean, CoordinateMedian, Krum, MultiKrum, Bulyan, FoolsGold |
| Adaptive | FedAdam, FedAdagrad, FedYogi |
| Privacy | DPAggregator (wraps any base), SecAgg, SecAggPlus |
All aggregators are composable. Wrap any base aggregator with differential privacy:
base = fedora.Krum(num_byzantine=2)
dp_agg = fedora.DPAggregator(base, config=fedora.DPConfig(epsilon=1.0))
This is central DP for replacement of one client's clipped update under a trusted
coordinator and fixed roster. DPConfig.public_weights supplies externally fixed
public client weights for a tighter weighted-average bound; client-reported
example counts are not evidence of public weights. Without that mapping, the
bound is conservatively 2 * clip_norm. Nonlinear aggregators clip the output delta and use a conservative sensitivity
bound, trading utility for a defensible release budget. The guarantee applies
to the privatized aggregate, not raw updates seen by the server or additional
diagnostic outputs. See DP scope and accounting.
Secure aggregation has multiple modes. SecAgg() selects the Shamir-backed
in-process evaluation mode; additive masking requires explicit mode="demo".
Neither provides an independently audited distributed cryptographic protocol.
Name and validate a target runtime protocol before making a deployment claim.
3. Built-in Attack Simulation
Test your defenses before deployment. 7 attack types ship with the framework:
from fedora.security.attacks import SignFlip, ScalingAttack, BackdoorAttack
def attack_fn(client_id):
if int(client_id) < 5: # First 5 clients are adversaries
return SignFlip()
return None
history = fedora.simulate(
client_fn=my_client_fn,
num_clients=20,
num_rounds=5,
attack_fn=attack_fn,
threat_model=fedora.ThreatModel(byzantine_fraction=0.25),
initial_parameters=params,
)
Attack types: LabelFlip, SignFlip, ScalingAttack, ModelReplace, BackdoorAttack, FreeRider, GradientInversion
4. Async-Capable Design
Three round execution modes for real-world deployments:
from fedora.engine.round import RoundConfig, RoundMode
# Synchronous: wait for all clients
sync = RoundConfig(mode=RoundMode.SYNC)
# Async (FedBuff): aggregate when buffer fills
async_buf = RoundConfig(mode=RoundMode.ASYNC, buffer_size=10)
# Deadline: aggregate whoever responds in time
deadline = RoundConfig(mode=RoundMode.DEADLINE, deadline_seconds=30.0)
Client selection strategies: Random, Stratified, Power-of-Choice, OORT
5. Pluggable Transport Layer
# Local (simulation)
from fedora.transport.local import LocalServerTransport
# gRPC (controlled deployment experiment)
from fedora.transport.grpc_transport import GrpcServerTransport
# WebSocket (browser/edge clients)
from fedora.transport.websocket_transport import WebSocketServerTransport
6. Evidence and Compliance Artifacts
Audit trails and receipts help reviewers understand what happened during an FL run. They can support regulated workflows, but they are not a substitute for a legal or security compliance review.
from fedora.security.audit import AuditTrail
trail = AuditTrail()
# Auto-logs: client joins, update rejections, attack detections,
# trust score changes, privacy budget consumption
trail.export_json("audit_report.json")
Benchmarks
Security Configuration Example
FedoRA's declarative approach is designed to reduce security setup effort:
| Approach | Lines of Code | Components Auto-Configured |
|---|---|---|
| FedoRA ThreatModel | 8 | Aggregator, DP, clipping, defenses, trust, audit |
| Manual configuration | 78 | Same components, hand-wired |
Attack Resilience
The benchmark harness is intended to compare no-defense, manual-defense, and FedoRA-recommended configurations under the same declared threat:
| Attack (30% Byzantine) | No Defense | Manual Krum | FedoRA Auto |
|---|---|---|---|
| SignFlip | Diverges | Converges | Converges |
| ScalingAttack | Diverges | Converges | Converges |
| ModelReplace | Diverges | Converges | Converges |
Run benchmarks yourself: python benchmarks/run_all.py. Treat published benchmark claims as release artifacts only when the environment, command, and raw output are committed with the result.
Test Suite
The suite has 1,464 passing tests across the FL core and the knowledge layer. Representative coverage:
| Area | Status |
|---|---|
| Engine (types, server, client, scheduler) | All passing |
| Aggregation (16 strategies + mixed-precision) | All passing |
| Clients (PyTorch, TF, JAX, sklearn, partial training) | All passing |
| Transport (local, gRPC, WebSocket) | All passing |
| Security (threats, attacks, defenses, trust, audit) | All passing |
| Knowledge spine (artifacts, mergers, state, wire format) | All passing |
| Knowledge mergers and adoption ladder | All passing |
| Knowledge seams (embedder fallback, subprocess sandbox) | All passing |
| Agent-memory gate experiment + capability benchmark | All passing |
Coming from Flower?
FedoRA ships bidirectional adapters and a migration assistant.
Use Your Flower Clients with FedoRA
from fedora.compat.flower import FlowerClientAdapter
# Wrap any existing Flower NumPyClient
fedora_client = FlowerClientAdapter(your_flower_client)
Use FedoRA Clients with Flower
from fedora.compat.flower import FedoraFlowerAdapter
# Wrap a FedoRA client for use in Flower
flower_client = FedoraFlowerAdapter(your_fedora_client)
Scan Your Flower Project
from fedora.compat.migration import MigrationHelper
helper = MigrationHelper()
report = helper.scan_flower_project("./my_flower_project")
report.print_migration_plan()
# Outputs: file-by-file migration steps, effort estimates, code examples
Architecture
fedora/
engine/ # Core types, server, client, round management, history
aggregation/ # 14 strategies: averaging, robust, adaptive, DP, secure
security/ # Threat model, attacks, defenses, trust scoring, audit trail
transport/ # Local, gRPC, WebSocket (pluggable via registry)
simulation/ # Runner, data distribution, virtual clients
compat/ # Flower adapters and migration tools
enterprise/ # Governance, compliance helpers, deployment utilities
Installation Options
# Core (numpy + typer)
pip install fedora-fl
# Test/development baseline
pip install -e ".[test]"
# With gRPC transport
pip install "fedora-fl[grpc]"
# With Flower compatibility
pip install "fedora-fl[flower]"
# With privacy extras (scipy, pandas)
pip install "fedora-fl[privacy]"
# Security/evidence layer at full capability (signed attestation, TLS, schema validation)
pip install "fedora-fl[security]"
# Federated knowledge: production embeddings for the memory merger
pip install "fedora-fl[knowledge]"
# Everything
pip install "fedora-fl[all]"
Documentation
- Getting Started — Installation and basic usage
- Worked Scenarios — Eight runnable end-to-end walkthroughs across both personas (Byzantine+privacy, healthcare, edge devices; agent knowledge, prototypes, distillation logits, LoRA adapters, executable skills)
- Scenario Reference — Quick reference for every built-in scenario
- Security & Defenses — Threat models, defenses, trust scoring, and audit trails
- Aggregation Strategies — Deep dive into available aggregation strategies
- Migration from Flower — Adapter API and code examples
- Backend Guide — Local, gRPC, Ray, Flower, and FLARE execution paths
- Backend Capability Matrix — Supported, experimental, adapter, and demo-only claims
- Proof Workflow — Reproducible local proof run and evidence bundle
- Knowledge Federation RFC — Design of the
fedora.knowledgelayer and its phases - Knowledge Artifact Spec v1 — Wire format, content addressing, and the merge contract
- Knowledge Benchmark — Gate experiment and the current knowledge capability matrix
- Repo Split — Two-package monorepo structure for
fedora-fl-securityandfedora-fl - FedoRA Plan / UFCG — Portable, auditable plan representation
- Competitive Comparison — What FedoRA should own and where other frameworks lead
- API Reference — Full API documentation
Citation
If you use FedoRA in research, please cite:
@software{fedora2026,
title = {FedoRA: Security-First Federated Learning and Federated Knowledge},
author = {FedoRA Contributors},
year = {2026},
version = {2.0.0},
url = {https://github.com/mlgorithm/FedoRA}
}
License
FedoRA is licensed under the Apache 2.0 License.
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines on:
- Setting up your development environment
- Running tests and quality checks
- Submitting pull requests
- Adding new aggregation strategies or attack simulations
Support
- Issues & Bugs: GitHub Issues
- Security: See SECURITY.md
Metadata
Release files for fedora-fl 2.1.0b2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fedora_fl-2.1.0b2.tar.gz | 723.6 kB | With provenance | Details for fedora_fl-2.1.0b2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fedora_fl-2.1.0b2-py3-none-any.whl | Python 3 | none | any | Details for fedora_fl-2.1.0b2-py3-none-any.whl |
Total release size: 1.4 MB
Release files / fedora_fl-2.1.0b2.tar.gz
| Download URL | fedora_fl-2.1.0b2.tar.gz |
|---|---|
| Size | 723.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d3956519343bb25896a298b41652f36227dd72d41c849fb6c2ae29c3a0dfbd03
|
|
BLAKE2b-256 checksum How to use checksums |
8a1385114fee6bc9874b7a2264c01d22b30fa83f7477402359eda2c1b18b3afa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.
Transparency logRelease files / fedora_fl-2.1.0b2-py3-none-any.whl
| Download URL | fedora_fl-2.1.0b2-py3-none-any.whl |
|---|---|
| Size | 630.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ca6f482b7d38a7d684cf636f29be86a0baf50bb3a8c5175e8f0d4cb858aa0c72
|
|
BLAKE2b-256 checksum How to use checksums |
053d4ab2eea42b927ff64678dd2d6c4e108b20c1e189138ccba04f076674b142
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.
Transparency logSecurity for fedora-fl 2.1.0b2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for fedora_fl-2.1.0b2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.