Revisiting Court Decisions

In 2008, Miami-Dade enacted Ordinance 08-34 requiring cranes be able to withstand load from 140 mph winds. Construction companies objected — they’d need to spend more money ensuring public safety, and really how often are 140 mph winds ripping through Miami? Courts deemed the local regulation to cover worker safety and not public safety; the OSHA requirement, which is something like 90 mph, superseded the local government’s Ordinance (I think the 11th Circuit decision actually said it was a multi-purpose regulation … but since the requirement touched on workplace safety, OSHA wins). I wonder, as cranes come crashing into buildings in downtown Miami, if the court would revisit that decision.

I worked for a company that operated each regional area as an independent entity. Each had their own set of rules, regulations, processes … they just shared a common HR staff and all of the money rolled up to the same ledger. Their “sell” to this approach was that it allowed different regions with different requirements to make rules that met their customer’s needs. The unfortunate example that got cited, though, was a military base out in Virginia. *That* region had a policy where, upon being deployed overseas, a military family could have their account flagged as forward deployed. The the account would not be suspended for non-payment and no collections attempts would be made. Which is nice – but why weren’t military bases in other regions afforded the same courtesy? Or customers stationed at the base in Virginia who happened to retain their cell phone from their family’s home in Kansas? Essentially, I could never understand what about cellular service could need to be customized for a specific region where it was a completely unreasonable policy in other regions. There are areas where a single nation-wide regulation makes sense.

Construction regulations, on the other hand, seem very location specific. And a area where a nationwide minimum standard would be far more reasonable. I doubt there’s a lot of concern about coastal flooding in Denver. Snow load regulations for equipment in South Texas is silly, but I wouldn’t want to sleep next door to a crane in NYC that didn’t fall under some snow load reg. Builders in Maine don’t need to worry too much about tornado damage, but construction sites between OKC and Tulsa can reasonably be required to lash down their materials at the end of each day to avoid debris being flung all over the countryside. And, yeah, cities in Southern Florida can reasonably want large pieces of equipment to have higher wind load ratings than a crane in Seattle.

Furthermore — why is it “states rights” people only support the state’s rights to be *more* Republican? Why should Cali need a waiver to have stricter air quality and fuel efficiency rules? Why should Miami be unable to have higher standards for wind force? It isn’t like Washington needed a waiver to set their minimum wage above the federal set-point.

Equifax Hack

First of all, saying half the population of the United States has had their personal information stolen might be accurate, but it’s the good marketing spin. 2016 numbers had 249,485,228 adults in the United States. That’s 57% of people over 18 who have had their personal data stolen. Now there are people with no credit history. It’s a bit of a thing when you first want to rent a flat or get a credit card … you have no credit history, and can’t get credit until you have one. Last I read, it was something like 14% of adults who have no credit record — meaning Equifax gave up information on 66% of the credit-having population.

Leaving aside the marketing spin on numbers, though, why the hell is a credit bureau storing my personal information in a retrievable format instead of a one-way hash? Performance, I assume … so I guess my question really is why were a couple of clock cycles considered more important than the security of my data? Some of the data is probably maintained in clear text because they use heuristic matching to link incoming data to entities. I’m guessing my info comes in with a name, address, creditor name, and account number. And they’ve got to be able to match up the thirty different iterations of my address to ingest the data. But there’s no reason for the account number to be stored unhashed – store the last two or three digits in a new column for display (Your XYZ account ending in ###). And there’s sure as hell no reason for the SSN to be stored unhashed – even if they’d have to store the full one hashed and the last four in another hash because some data doesn’t come in with full SSNs.

Calculating Cost Of Material For Craft Projects — Crocheting and Knitting

Calculating the cost of materials for a knitting or crocheting project is a little more complex than calculating soap material costs. Because there’s not a recipe. Your pattern may say 150 grams of a specific yarn, but you don’t use exactly 150 grams. You use what you use, and whatever is left over is left over.

As with soap oils, the price per skein of yarn may include a tax or shipping component. You can follow the same process to determine the yarn as a percentage of the order weight for prorated shipping and the yarn cost as a percentage of the order cost for prorated tax.

With yarn projects, though, you need to know how much yarn actually went into the project. How? Weigh the skeins. Weigh them before you use them or just accept the manufacturer’s weight as accurate. If you’ve got a little kitchen scale, weigh the yarns when you finish using it on the project (this assumes you don’t concurrently use the same yarn on multiple projects!). The difference is the amount of yarn in the project. You can then calculate the percentage of the yarn which was used ( (weight at start – weight at end) / weigh at start). The material cost is that percentage of the yarn cost (price per skein * number of skeins used). Add up the material cost for each yarn in the project, and you know the material cost for the project.

A spreadsheet is good for these sort of repetitive calculations. You can estimate a project’s total cost by entering 0 into column ‘G’ and basing column ‘C’ on the pattern’s yarn requirements.

The spreadsheet allows you to check out how different yarns will impact the project material cost too – what happens if I use a more expensive yarn? It’s nice to know before looking at your shopping cart total in absolute shock 🙂

Calculating Cost Of Material For Craft Projects — Soap

Tax accounting doesn’t require you to track per-item cost of materials. Money for inventory on a shelf v/s money for inventory used in products  – same diff. But if you want to know how much you are profiting for each sale, it helps to track the cost of goods per item.

Soap is fairly easy because there’s a recipe — you know how much of a certain oil you’ve used in the end product because you weighted it out to the nearest tenth gram to start with. You still have to know how much you paid for that oil (well, close enough – prices change and I’m not interested in the level of accuracy which would require knowing from *which* order the oil I’m using *this* time came). But did you pay shipping and/or tax? If not, then the cost per gram is simply the price you paid divided by the number of grams purchased. If you *did* pay shipping or tax — then you need to calculate each item as a percentage of the order. You can do this just as a percentage of the total order cost ($ for item / $ for total order) and use that for both tax (accurate) and shipping (accurate if shipping is assessed by order value, probably close enough if shipping is assessed by weight). Or you can calculate the percentage of total order cost and the percentage of order weight (item weight / sum of weight of all items ordered). Use the order cost % for for tax calculations and the order weight % for shipping calculations. Then multiply tax and shipping charges by their respective % values.

A 35# pail of coconut oil for 43.78$ with no shipping but 3.28$ in tax as the only item ordered = 47.06$. 35# is 560 ounces (I trust the supplier’s scale here). Which is 0.084 cents per ounce. My 20% superfat coconut oil soap recipe uses 66 ounces. That’s 5.54$ of coconut oil.

Lye cost is a more complex calculation because I order it along with other specialty items. It was 50$ for the whole order of lye. The lye was 85% of the previous order’s weight. Shipping was 17.79. So the lye’s portion of the shipping was 0.85 * 17.79 = 15.12$. The lye was 61% of the order’s value. Tax was 6.19. The lye’s portion of tax was 0.61 * 6.19 = 3.78$. The sum of these (50+15.12+3.78) is 68.9. Each container is 27 ounces of lye and I got 5 containers — 27 * 5 is 135 ounces. Divide the lye cost by ounces received, 68.9/135, and I paid 0.51$ per ounce of lye. There are 9.6 ounces of lye in my recipe, which adds 4.90$ for lye.

Lavender essential oil was 33.54$ for 16.6 ounces. 16.07$ shipping, and the EO was 7% of the order weight. That’s another 1.12$ for shipping. Total cost for the EO is 34.66. Divide by ounces and it is 2.03$ per ounce. I used 4 ounces of the EO – 8.37$

The lavender scented, uncoloured batch of my coconut oil soap costs 5.54 + 4.90 + 8.37 = 18.82$ to produce. Now this is a 6# batch of soap, 24 3-oz bars. To calculate a per-bar cost, divide the total batch cost by the number of bars cut. 18.82 / 24 = 0.78$.

This is the sort of thing databases and spreadsheets are really good at doing. It’s the same formula over and over again. There are specialty accounting packages specifically for individual craft segments (i.e. a single piece of software that tracks inventory and unit cost thereof, recipes, sales and unit costs thereof and can analyze the data all sorts of ways). 100$ for the software, which is deductible against business income – it’s an investment in the business and saving yourself time. But for an initial foray into marketing a product, a simple spreadsheet will do. SoapCostCalculator is a spreadsheet I built to get an idea of how much each bar of soap was costing me.

ZoneMinder After Upgrade

We recently updated from ZoneMinder 1.30 to 1.34 – easy as can be, ran the DB update script and everything came right online. Except … our home automation system hasn’t been able to access the system. OpenHAB reports that the bridge is offline. And we’re getting 404 errors in all of the /zm/api calls in access_log.

Turns out the API was offline because when the new package came down … there was a zoneminder.conf.rpmnew in the Apache conf.d directory. Can’t even say I found this intentionally – I wanted to check the Apache config file to see if it had anything about the api directory, did a directory listing, and said oooooh!

[lisa@fedora01 conf.d]# ll zone*
-rw-r–r– 1 root root 1990 Jul 29 18:13 zoneminder.conf
-rw-r–r– 1 root root 1990 Aug 28 22:34 zoneminder.conf.rpmnew

They’ve changed a few of the sub-directories and added components to the config. As soon as I renamed zoneminder.conf to zoneminder.conf.old, copied zoneminder.conf.rpmnew to zoneminder.conf, and repeated a few config tweaks we had made for the original installation … restarted Apache and voila, we can fetch /zm/api/host/getVersion.json and get values. So if you’re getting odd 404 errors and CakePHP “/zm/api” not found errors maybe you forgot to update your config with changes from the rpmnew file.

Cleaning Up Old OpenHAB Persistence Tables

So my husband asked for a program that would go out to the OpenHAB persistence database and identify all of the item tables that are no longer associated with active items. If you rename or delete an item from OpenHAB, the associated data is retained in the persistence database. Might be a good thing – maybe you wanted that data. But if it’s useless fluff … well, no need to keep the state changes from a door sensor that’s no longer around.

Wrote the code, and asked him how many days old he wanted the last update to be before the item table got dropped … and he told me this was a useless way to do it and maybe something really hadn’t updated in six months or three years and age of last update is no way to be identifying tables to be removed. Which, yeah, then why ask for it!? Then I needed to write something that takes a list of items from OpenHAB and identifies everything in the items table that does not appear in the OpenHAB list so those tables can be deleted. But I figured I’d post the original code too in case anyone else could use it. Both in perl, and neither in particularly well written perl. I trust the data and don’t want to protect against insertion attacks.

Drop tables for items that no longer appear in OpenHAB:

use strict;
use DBI;

my %strItemsFromOpenHAB = ();
open(INPUT,"./openhabItemList.txt");
while(<INPUT>){
        chomp();
        my $strCurrentItem = $_;
        $strItemsFromOpenHAB{$strCurrentItem}++;
}
close INPUT;

my $dbh = DBI->connect('DBI:mysql:openhabdb;host=DBHOST', 'DBUID', 'DBPassword', { RaiseError => 1 } );

my $sth = $dbh->prepare("SELECT * FROM items");
$sth->execute();
while (my @row = $sth->fetchrow_array) {
        my $strItemID = $row[0];
        my $strItemName = $row[1];
        if(! $strItemsFromOpenHAB{$strItemName} ){              # If the current item name is not in the list of items from OpenHAB
#               print "DELETE FROM items where ItemID = $strItemID\n";
                print "DROP TABLE Item$strItemID;  # $strItemName \n";
        }
}
$sth->finish();

$dbh->disconnect();
close OUTPUT;

 

Identify tables that have not been updated in iTooOldInDays days:

use strict;
use DBI;
use Date::Parse;
use Time::Local;

my $iTooOldInDays = 365;

my $iCurrentEpochTime = time();

my @strItems = ();
my $iItems = 0;

my $dbh = DBI->connect('DBI:mysql:openhabdb;host=DBHOST', 'DBUID', 'DBPassword', { RaiseError => 1 } );

my $sth = $dbh->prepare("SELECT * FROM Items");
$sth->execute();
while (my @row = $sth->fetchrow_array) {
        $strItems[$iItems++] = $row[0];
}
$sth->finish();

for(my $i = 0; $i < $iItems; $i++){ my $strTableName = 'Item' . $strItems[$i]; my $sth = $dbh->prepare("SELECT * FROM $strTableName ORDER BY Time DESC LIMIT 1");
        $sth->execute();
        while (my @row = $sth->fetchrow_array) {
                my $strUpdateTime = $row[0];
                my @strDateTimeBreakout = split(/ /,$strUpdateTime);
                my $strDate = $strDateTimeBreakout[0];
                my $strTime = $strDateTimeBreakout[1];

                my @strDateBreakout = split(/-/,$strDate);
                my @strTimeBreakout = split(/:/,$strTime);

                my $iUpdateEpochTime = timelocal($strTimeBreakout[2],$strTimeBreakout[1],$strTimeBreakout[0], $strDateBreakout[2],$strDateBreakout[1]-1,$strDateBreakout[0]);
                my $iTableAge = $iCurrentEpochTime - $iUpdateEpochTime;

                if($iTableAge > ($iTooOldInDays * 86400) ){
                        print "$strTableName last updated $strUpdateTime - $iUpdateEpochTime\n";
                }
        }
        $sth->finish();
}

$dbh->disconnect();
close OUTPUT;

Configuring and Using RPZ

I realized today what, while I had written about why response policy zones are useful, I never indicated how to configure one! So here’s a quick document outlining how to set it up in ISC Bind. In your named.conf file, add a response policy to your options section:

        response-policy {
                zone “rpz”;
        };
Then add the correspondingly named zone at the end of the file. For purposes of testing, I added a zone as a forward only zone so I could perform a network capture to see what exactly transpires when a name in the RPZ is resolved.
zone “rpz” {
      type master;
      file “rpz.db”;
      allow-query { none; };
      allow-transfer { none; };
};
zone “windstream.com” {
    type forward;
    forward only;
    forwarders { 8.8.8.8; };
};
Then you just have to make a rpz.db where you store your named files:
$TTL 60
$ORIGIN rpz.
@            IN    SOA  localhost. root.localhost.  (
                          2   ; serial
                          3H  ; refresh
                          1H  ; retry
                          1W  ; expiry
                          1H) ; minimum
                  IN    NS    localhost.

www.windstream.com    CNAME    www.yahoo.com.
Restarted named and ran “rndc flush” to avoid serving cached content instead of the RPZ host data. Then ran a few tests and confirmed that the resolution configured in the rpz zone:
[lisa@fedora02 named]# dig +short www.windstream.com @localhost
www.yahoo.com.
atsv2-fp.wg1.b.yahoo.com.
98.139.183.24
98.138.252.30
98.139.180.149
98.138.253.109
[lisa@fedora02 named]# dig +short dell905.windstream.com @localhost
ns4.windstream.com.
173.186.244.139
[lisa@fedora02 named]# dig +short www.google.com @localhost
216.58.218.228
In this process, I learnt something interesting about ICS’s implementation of RPZ: it still performs the query and then overrides the results. Odd waste of cycles, but the resolution that was subsequently turned into yahoo’s address from the rpz zone. Looking up a windstream.com host that isn’t in my RPZ and I got another query out to 8.8.8.8 which was expected. Query to something not in the forward zone and not in the rpz zone and I get no traffic to 8.8.8.8 (because it follows my normal forwarding which is to our ISP’s DNS).
I was curious if this meant rpz could not be used to publish a bad hostname locally – but attempting to resolve a bad hostname (added abadhost.windstream.com with the same CNAME to Yahoo and reloaded my zone) worked just fine.

[root@fedora02 ~]# dig abadhost.windstream.com @localhost

; <<>> DiG 9.11.1-P2-RedHat-9.11.1-2.P2.fc26 <<>> abadhost.windstream.com @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8382
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 4, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 1aa34751c5df7f78857a921259a8706fb5e1741a46eb5352 (good)
;; QUESTION SECTION:
;abadhost.windstream.com. IN A

;; ANSWER SECTION:
abadhost.windstream.com. 5 IN CNAME www.yahoo.com.
www.yahoo.com. 1800 IN CNAME atsv2-fp.wg1.b.yahoo.com.
atsv2-fp.wg1.b.yahoo.com. 60 IN A 98.139.180.149
atsv2-fp.wg1.b.yahoo.com. 60 IN A 98.138.253.109
atsv2-fp.wg1.b.yahoo.com. 60 IN A 98.139.183.24
atsv2-fp.wg1.b.yahoo.com. 60 IN A 98.138.252.30

;; AUTHORITY SECTION:
wg1.b.yahoo.com. 172800 IN NS yf3.a1.b.yahoo.net.
wg1.b.yahoo.com. 172800 IN NS yf4.a1.b.yahoo.net.
wg1.b.yahoo.com. 172800 IN NS yf1.yahoo.com.
wg1.b.yahoo.com. 172800 IN NS yf2.yahoo.com.

;; ADDITIONAL SECTION:
yf1.yahoo.com. 86400 IN A 68.142.254.15
yf2.yahoo.com. 86400 IN A 68.180.130.15

;; Query time: 1204 msec
;; SERVER: ::1#53(::1)
;; WHEN: Thu Aug 31 16:24:15 EDT 2017
;; MSG SIZE rcvd: 315

But there is a query that goes out to the name server and a ‘no such name’ result returned. Odd.

Cooperation

Read an interesting take on Mueller’s coordination with NY AG Schneiderman: Trump might manage to shut down Mueller’s investigation (or enough Republicans may OK the 6 month time limit). Justice can suppress documents from the investigation (or oopse them), but it would be a gross abuse of federal power to confiscate (or even assume to control the release of) investigative materials in possession of the NY AG.

Which isn’t to say Trump & co wouldn’t *try* … but something not a lot of Americans seem to know about the lead up to the Revolutionary war: there was quite a bit of debate in Parliament about the same grievances the American colonialists had. Not because Britons had some altruistic concern for the socio-political well-being of Colonials, but if some set of offensive rules apply to THOSE crown citizens today, what is to stop them from applying to ME tomorrow? Point being – it’s one thing to treat women horrendously, screw over poor people, take the David Duke approach to race relations. But if the feds can come in and overrule state criminal investigations in NY today … well, here’s hoping people who like to prance around screaming about states rights have some line they aren’t OK with Trump crossing.

Pardons

When a law enforcement officer refuses to enforce the law and can rely on the president to pardon the infraction, does that not elevate the executive branch above all others? Trump encouraged law enforcement officers to abuse people in their custody (full on Jerry Seinfeld why are they so careful getting the guy in the back of the cruiser?). Can police officers expect to be pardoned when charged with brutality? Will they be guaranteed their jobs even after killing a suspect? What is the point of having laws (or a court system) if one branch of the government can decide what should be legal by pardoning infractions they don’t like.

Sure there are mitigating circumstances that may diminish the severity of the infraction, mandatory sentencing produced people whose ‘time’ in no way fit their ‘crime’, some people are amazingly reformed after the commission of their crime. Hell, the law could change five years into your term rendering your infraction a perfectly legal activity. Some people deserve a break. Would it not be better to allow the judicial system to redress these scenarios? Mechanisms to do so are already in place — parole reduces the effective sentence, but the individual retains a criminal record. Expunction seals the record and generally means the individual does not need to disclose the conviction.

And not that I believe Trump is in the least bit concerned about people whose rights were trampled by Arpaio? What redress do they have? The purported ideology does not care who is damaged in the pursuit of illegal immigrants. And that is what makes this particular pardon so offensive. In the ‘war on drugs’, cops abused people in poor neighborhoods. Evidence was planted to convict those who were known to be dealers. What would have happened if Reagan had just pardoned those officers?

We watched a lot of movies when building Windstream. A lot. We were splitting an eDirectory tree, and a couple of servers each night would be moved. I ran the support bridge for the split, and needed a way to get a good number of people to volunteer to work 6p-2a six days a week with no overtime. Accomplished this by having free dinner, snacks, and movies. I didn’t own that many DVDs, so people volunteered to bring their collection too. It was a lot of fun (some of the techs ringing into the bridge would get the same DVD going and watch with us), and I got to see a lot of movies I wouldn’t have known existed. One of those movies was an early 70’s movie based on a mid 60’s book: Colossus: The Forbin Project. Pardoning Arpaio makes me think of the movie — the premise was essentially that the US government commissioned a computer system to control the country’s nuclear arsenal with the goal of preserving world peace because computers do not suffer human foibles such as irrational emotional responses. The computer accomplished it’s goal … by using the nuclear arsenal to blackmail humanity into peace (either you stop fighting or I start nuc’ing you until you concede). Same lack of constraint or morality. It doesn’t matter how many people are tortured or killed, as long as the objective is met.