Sunday, August 30, 2026

Android disaster with Google Play

New Samsung phone, I'm helping someone install everything. Everything is going well, apps are updating. WhatsApp is transferring data. I uninstall several unwanted apps, including Outlook and LinkedIn. I restart. The Play Store stops launching.

This is quite serious; it can't be that the Play Store isn't working. I'm trying the standard method, clearing the memory and data for the Play Store and Google Services, and restarting.

Nothing. Gemini suggests I should install APK manually. It must be kidding.

Two or three restarts later, I notice that I get a monit that asks if I want to restore Outlook and LinkedIn. I discarded this prompt twice but this time I decide to give it a try.

Play store appears as notification and shows it's installing the two.

A minute later, the notification disappears and I try Play Store once again.

It works.

It's utterly shameful that uninstalling two third-party apps can break such fundamental system service as Google Play. I don't care whose fault this is, Google, Samsung and its Knox.

It should never, ever happen. Shame on you.

Monday, August 10, 2026

Functional programming in JavaScript (12)

Please take a look at other posts about functional programming in JavaScript:

  1. Part 1 - what Functional Programming is about
  2. Part 2 - Functional Pipelines
  3. Part 3 - the Y Combinator
  4. Part 4 - Monads
  5. Part 5 - Trampoline
  6. Part 6 - Lenses
  7. Part 7 - Church encoding (booleans)
  8. Part 8 - Church encoding (arithmetics)
  9. Part 9 - Church encoding (if, recursion)
  10. Part 10 - Church encoding (lists)
  11. Part 11 - Church encoding (strings, objects)
  12. Part 12 - modularity

Modularity lets us create code that spans multiple modules (technically: files).

But how it works under the hood? How do import and export actually work in a functional way? How it is possible to have cyclic dependencies between modules?

We are going to build a short example of three modules: A, B and Main. Modules A and B will depend on each other.

Let's start with the code:

// ==========================================
// Infrastructure
// ==========================================
const registry = {};

function registerModule(id, factoryFn) {
    registry[id] = {
        id,
        factoryFn,
        exports: {},        
        isEvaluated: false  
    };
}

function evaluateModule(id) {
    const mod = registry[id];
    
    if (mod.isEvaluated) {
        return mod.exports;
    }

    mod.isEvaluated = true;

    const _import = (dependencyName) => {
        return evaluateModule(dependencyName);
    };

    const _export = (name, fn) => {
        mod.exports[name] = fn;
    };

    mod.factoryFn(_import, _export);

    return mod.exports;
}

// ==========================================
// Example use
// ==========================================

// Module A (a.js) - cyclic dependency to B
registerModule('./a.js', (_import, _export) => {
    const _b = _import('./b.js');

    let valueA = "Wartość z A";

    _export('getA', () => valueA);
    _export('callB', () => "A calls B -> " + _b.getB() );
});

// Module B (b.js) - cyclic dependency to A
registerModule('./b.js', (_import, _export) => {
    const _a = _import('./a.js');

    let valueB = "Wartość z B";

    _export('getB', () => valueB);
    _export('callA', () => "B calls A -> " + _a.getA() );
});

// main module (main.js)
registerModule('./main.js', (_import, _export) => {
    const _a = _import('./a.js');
    const _b = _import('./b.js');

    console.log(_a.callB());
    console.log(_b.callA());
});

evaluateModule('./main.js');

Look how simple it is. We have a global registry of modules. Our register function just adds a module to the registry.

The only non trivial function here is the evaluation function. The function executes module's factory function.

Whenever we execute the import, we just recursively call the evaluation function. And this is where a problem with cyclic dependencies could possibly occur.

How do we prevent it?

    ...
    if (mod.isEvaluated) {
        return mod.exports;
    }

    mod.isEvaluated = true;

We check if module is already evaluated and if it is, we just return its exports - but the actual list of module's exports can possibly be empty at this point! In fact, the list of module's exports can be available only after the module initialization is complete!

That's why we only export functions and we call the evaluation of the main module only when the dependency graph is fully evaluated (all exports are available). If a module is imported multiple times (by other modules), its factory function is evaluated only once, all subsequent initializations terminate early.

Monday, June 1, 2026

Don't just "Trim unused code"

Trimming unused code works great in NET Core.

Until it doesn't.

An example:

  • integration library with multiple DataContract/DataMember models for Core.WCF
  • "Trim unused code" trims away setters as it considers setters are not used
  • WCF initializer throws InvalidDataContractException: No get method for property 'Foo' in type 'Bar'
  • 3 hours wasted on debugging this

Yes, you can possibly add some code to a list of trimmer exceptions. And yes, you have to know that the trimmer is the culprit, in the first place.

Thursday, May 28, 2026

A lesson learned about JWT tokens "Issued At" attribute

One of our systems integrates with Apple Pay and a JWT token is used to authenticate server-to-server requests from us to their backends. Someone noticed that a small amount of requests fail. It was usually less than 5% of failed requests, raising to 30% occasionally for short period of times.

The code was audited and we've found that someone just wrote:

private string GetToken()
{
	var now    = DateTime.UtcNow;
	var expiry = now.AddSeconds(this.Settings.MaxTokenAge);

	ECDsaSecurityKey eCDsaSecurityKey = GetEcdsaSecuritKey();

	var handler = new JsonWebTokenHandler();
	string jwt = handler.CreateToken(new SecurityTokenDescriptor
	{
		Issuer   = this.Settings.IssuerId,
		Audience = this.Settings.AppstoreAudience,
        
		NotBefore = now,
		Expires   = expiry,
		IssuedAt  = now,
		Claims    = new Dictionary<string, object>
		{
        	...
		},

		SigningCredentials = ...
	});

	return jwt;
}

Looks great.

Problem is, it does not always work.

What we've found out is that when there's a subtle, small difference of current time between your servers and their servers, our DateTime.UtcNow can be their future. And they (correctly) reject tokens from the future.

What was applied there? Well, just:

private string GetToken()
{
	var now    = DateTime.UtcNow.AddMinutes(-1);
	var expiry = now.AddSeconds(this.Settings.MaxTokenAge);

The result? 0% of failed requests.

Lesson learned.

Wednesday, April 22, 2026

Local WebAuthn/FIDO2 environment

In last 2 years, we add WebAuthn/FIDO2 support to our server web apps. It works great and has multiple advantages over classical authentication. The whole idea of passwordless authentication is just awesome.

It was not long ago when I realized that testing FIDO2 in Chromium-based browsers is as easy as enabling WebAuthn tab in Developer's console! It's just there! Just hit F12 and either just add + to add a new tab or click three-dots and pick More tools. Then just click WebAuthn and you'll get a local WebAuthn client that lives until you close the browser. Perfect for testing!

If you need a gentle WebAuthn introduction, visit webauthn.io for more information.

Friday, April 17, 2026

Good bye Total Commander, welcome Double Commander

After like 30 years of using Total Commander (and being a proud owner of a personal license), I finally give up using it in favor of a worthy replacement that works everywhere, including Linux. Double Commander, welcome on the board.

To make it even more "Total Comanderish", go to Options and tweak some of them:

  • Fonts/Main font - Microsoft Sans Serif, Bold, 9
  • File views/Columns/Auto fill columns - on
  • File views/Columns/Auto size column - First
  • File views/File views extra/Show system and hidden files - on
  • Icons/Show overlay icons - on
  • Icons/Icon size/File panel - 16x16
  • Miscellaneous/Show splash screen - off
  • Terminal/Command to run terminal and keep open - Command: wt, Parameters: new-tab --hold {command}
  • Terminal/Command to run terminal and close - Command: wt, Parameters: new-tab {command}
  • Terminal/Command for just running terminal - Command: wt, Parameters: -d .

Monday, March 9, 2026

C# - a callable with custom data

Have you ever wondered if a C# delegate can contain a custom field or property?

No, it can't, classes that are delegates are closed for extensions - one would say.

In other words, C# can't mimick JavaScript, where you can attach anything to a function - this pattern is useful when implementing some functional patterns like memoization.

A side note - TypeScript is flexible enough, you can have a type that describes an object that is callable and yet contains some data:

type Callable = {
    description: string;
    (a: string): string;
}

But let's go back to C#. Is it really not possible? Well, not directly. However, there's a clever way of forcing an object of any shape to be implicitely convertible to a function type. And this implicit conversion would take place when the object would be passed to an auxiliary function, as an argument!

public class Program
{
	/// <summary>
	/// Auxiliary executor
	/// </summary>
	static string Executor(Func<string, string> logic, string input)
	{
		return logic(input); 
	}

	static void Main(string[] args)
	{
		Callable c = new Callable()
		{
			Description = "custom description"
		};

		string result = Executor(c, "FooBar");
		Console.WriteLine(result);
	}
}

public class Callable
{
	public string Description { get; set; }

	/// <summary>
	/// Internal implementation details of the "callable" interface
	/// </summary>
	private string Invoke(string param) => $"Argument: {param}, this.Description: {Description}";

	/// <summary>
	/// Public implicit conversion
	/// </summary>
	public static implicit operator Func<string, string>(Callable c) => c.Invoke;
}